Vue集成 #
安装 #
bash
npm install algoliasearch vue-instantsearch
基本配置 #
Vue 3 配置 #
javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import InstantSearch from 'vue-instantsearch/vue3/es';
const app = createApp(App);
app.use(InstantSearch);
app.mount('#app');
创建搜索组件 #
vue
<template>
<ais-instant-search
index-name="products"
:search-client="searchClient"
>
<ais-search-box placeholder="搜索商品..." />
<ais-hits>
<template v-slot:item="{ item }">
<div class="hit">
<h3>{{ item.name }}</h3>
<p>${{ item.price }}</p>
</div>
</template>
</ais-hits>
</ais-instant-search>
</template>
<script>
import algoliasearch from 'algoliasearch';
export default {
data() {
return {
searchClient: algoliasearch('APP_ID', 'SEARCH_KEY')
};
}
};
</script>
核心组件 #
ais-instant-search #
vue
<ais-instant-search
index-name="products"
:search-client="searchClient"
:initial-ui-state="{
products: {
query: 'iphone',
page: 1
}
}"
>
<!-- 子组件 -->
</ais-instant-search>
ais-search-box #
vue
<ais-search-box
placeholder="搜索商品..."
:autofocus="true"
:search-as-you-type="true"
:show-reset="true"
:show-submit="true"
:show-loading-indicator="true"
/>
ais-hits #
vue
<ais-hits>
<template v-slot:item="{ item }">
<div class="hit">
<img :src="item.image" :alt="item.name" />
<h3>{{ item.name }}</h3>
<p>${{ item.price }}</p>
</div>
</template>
</ais-hits>
分页组件 #
ais-pagination #
vue
<ais-pagination
:show-first="true"
:show-previous="true"
:show-next="true"
:show-last="true"
:padding="2"
/>
ais-infinite-hits #
vue
<ais-infinite-hits>
<template v-slot:item="{ item }">
<div class="hit">
<h3>{{ item.name }}</h3>
<p>${{ item.price }}</p>
</div>
</template>
<template v-slot:loadMore="{ refineNext, isLastPage }">
<button
:disabled="isLastPage"
@click="refineNext"
>
加载更多
</button>
</template>
</ais-infinite-hits>
过滤组件 #
ais-refinement-list #
vue
<ais-refinement-list
attribute="brand"
searchable
searchable-placeholder="搜索品牌"
:show-more="true"
:show-more-limit="20"
:limit="5"
/>
ais-menu #
vue
<ais-menu
attribute="category"
:show-more="true"
:limit="5"
/>
ais-toggle-refinement #
vue
<ais-toggle-refinement
attribute="inStock"
label="仅显示有货"
/>
ais-range-input #
vue
<ais-range-input
attribute="price"
:min="0"
:max="2000"
:precision="0"
/>
排序组件 #
ais-sort-by #
vue
<ais-sort-by
:items="[
{ value: 'products', label: '相关度' },
{ value: 'products_price_asc', label: '价格升序' },
{ value: 'products_price_desc', label: '价格降序' }
]"
/>
状态组件 #
ais-current-refinements #
vue
<ais-current-refinements>
<template v-slot:item="{ item }">
<span>{{ item.label }}: {{ item.display }}</span>
</template>
</ais-current-refinements>
ais-clear-refinements #
vue
<ais-clear-refinements
:excluded-attributes="['query']"
/>
ais-stats #
vue
<ais-stats>
<template v-slot="{ nbHits, processingTimeMS }">
找到 {{ nbHits }} 个结果,耗时 {{ processingTimeMS }}ms
</template>
</ais-stats>
自定义组件 #
使用Composition API #
vue
<template>
<ais-instant-search
index-name="products"
:search-client="searchClient"
>
<CustomSearchBox />
<CustomHits />
</ais-instant-search>
</template>
<script setup>
import { useSearchBox, useHits } from 'vue-instantsearch/vue3/es';
const searchClient = algoliasearch('APP_ID', 'SEARCH_KEY');
function CustomSearchBox() {
const { query, refine } = useSearchBox();
return {
query,
refine
};
}
function CustomHits() {
const { hits } = useHits();
return {
hits
};
}
</script>
使用Options API #
vue
<template>
<div>
<input
:value="query"
@input="refine($event.target.value)"
placeholder="搜索..."
/>
<div v-for="hit in hits" :key="hit.objectID">
<h3>{{ hit.name }}</h3>
<p>${{ hit.price }}</p>
</div>
</div>
</template>
<script>
import { connectSearchBox, connectHits } from 'instantsearch.js/es/connectors';
export default {
props: ['query', 'refine', 'hits']
};
export const CustomSearchBox = connectSearchBox({
render({ currentRefinement, refine }) {
return {
query: currentRefinement,
refine
};
}
});
</script>
完整示例 #
vue
<template>
<ais-instant-search
index-name="products"
:search-client="searchClient"
>
<ais-configure
:hits-per-page.camel="12"
:attributes-to-highlight.camel="['name', 'description']"
/>
<div class="search-container">
<aside class="filters">
<h3>筛选</h3>
<ais-clear-refinements />
<h4>品牌</h4>
<ais-refinement-list attribute="brand" searchable />
<h4>分类</h4>
<ais-refinement-list attribute="category" />
<h4>价格</h4>
<ais-refinement-list attribute="price_range" />
</aside>
<main class="results">
<div class="search-header">
<ais-search-box placeholder="搜索商品..." />
<ais-sort-by
:items="[
{ value: 'products', label: '相关度' },
{ value: 'products_price_asc', label: '价格升序' },
{ value: 'products_price_desc', label: '价格降序' }
]"
/>
</div>
<div class="search-info">
<ais-stats>
<template v-slot="{ nbHits }">
找到 {{ nbHits }} 个结果
</template>
</ais-stats>
<ais-current-refinements />
</div>
<ais-hits>
<template v-slot:item="{ item }">
<article class="product-card">
<img :src="item.image" :alt="item.name" />
<div class="product-info">
<h3>{{ item.name }}</h3>
<p class="brand">{{ item.brand }}</p>
<p class="price">${{ item.price }}</p>
<p class="rating">★ {{ item.rating }}</p>
</div>
</article>
</template>
</ais-hits>
<ais-pagination />
</main>
</div>
</ais-instant-search>
</template>
<script>
import algoliasearch from 'algoliasearch';
import 'instantsearch.css/themes/algolia.css';
export default {
data() {
return {
searchClient: algoliasearch('APP_ID', 'SEARCH_KEY')
};
}
};
</script>
<style scoped>
.search-container {
display: flex;
gap: 20px;
}
.filters {
width: 250px;
}
.results {
flex: 1;
}
.product-card {
border: 1px solid #eee;
border-radius: 8px;
padding: 16px;
}
.product-card img {
width: 100%;
height: 200px;
object-fit: cover;
}
</style>
样式定制 #
自定义类名 #
vue
<ais-search-box
:class-names="{
'ais-SearchBox': 'my-search-box',
'ais-SearchBox-input': 'my-search-input',
'ais-SearchBox-submit': 'my-search-submit'
}"
/>
自定义样式 #
css
.my-search-box {
margin-bottom: 20px;
}
.my-search-input {
width: 100%;
padding: 12px;
border: 2px solid #ddd;
border-radius: 8px;
}
.my-search-input:focus {
border-color: #5468ff;
outline: none;
}
总结 #
Vue集成要点:
| 要点 | 说明 |
|---|---|
| 核心组件 | ais-instant-search, ais-search-box, ais-hits |
| 过滤组件 | ais-refinement-list, ais-menu, ais-toggle-refinement |
| 分页组件 | ais-pagination, ais-infinite-hits |
| 插槽 | v-slot:item, v-slot:loadMore |
| 样式 | class-names属性,自定义CSS |
接下来,让我们学习 Node.js后端。
最后更新:2026-03-28