基于Nuxt和Vuex实现自动补全搜索:选Algolia还是纯JavaScript方案?
Nuxt.js 搜索自动补全方案选型及代码优化
方案选型判断标准
两个方案均合理,具体选型根据你的业务场景决定:
- 优先选纯JS实现的场景:
- 备选搜索数据总量小于1000条,可一次性全量加载到前端
- 仅需要简单的字段匹配逻辑,不需要拼写纠错、权重排序、多字段联合搜索等高级功能
- 项目体量小,不想引入额外第三方服务成本
- 优先选Algolia实现的场景:
- 搜索源数据量过万,前端全量加载会占用过多带宽、拖慢首屏加载速度
- 需要高级搜索能力,比如拼写容错、同义词匹配、搜索结果权重排序、搜索数据统计分析等
- 多端复用搜索逻辑,比如除了Web端外,APP、小程序也需要用到相同的搜索能力
现有纯JS代码优化
你当前的代码存在几个可优化点:v-for循环的是原始items数组而不是过滤后的filteredResults计算属性、没有加输入防抖、没有做建议列表的显示隐藏控制,优化后代码如下:
<template> <label class="block relative"> <span class="text-gray-700 font-bold">{{ label }}</span> <input type="search" class="mt-1 block w-full rounded-md border-0 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 bg-transparent" autocomplete="off" :placeholder="placeholder" v-model="keyword" @input="handleInput" @blur="showSuggest = false" @focus="keyword && (showSuggest = true)" > <!-- 建议列表,有结果且需要显示时展示 --> <ul v-if="showSuggest && filteredResults.length" class="absolute z-10 w-full bg-white border rounded-md mt-1 max-h-60 overflow-auto"> <li v-for="item in filteredResults" :key="item.id" class="px-3 py-2 hover:bg-indigo-50 cursor-pointer"> <NuxtLink :to="`/detail/${item.id}`" class="block w-full"> {{ item.icao }} - {{ item.name }} </NuxtLink> </li> </ul> <!-- 无结果提示 --> <div v-if="showSuggest && keyword && !filteredResults.length" class="absolute z-10 w-full bg-white border rounded-md mt-1 px-3 py-2 text-gray-500"> 暂无匹配结果 </div> </label> </template> <script> import { defineComponent } from "@vue/composition-api"; // 防抖工具函数 function debounce(fn, delay = 300) { let timer = null; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); } } export default defineComponent({ data() { return { keyword: "", showSuggest: false, }; }, computed: { filteredResults() { if (!this.keyword.trim()) return []; const lowerKeyword = this.keyword.toLowerCase(); return this.items.filter(item => item.icao.toLowerCase().includes(lowerKeyword) // 可扩展多字段匹配,比如同时匹配机场名称 // || item.name.toLowerCase().includes(lowerKeyword) ); }, }, methods: { // 输入防抖,避免频繁触发过滤逻辑 handleInput: debounce(function() { this.showSuggest = !!this.keyword.trim(); }, 200) }, props: { label: String, placeholder: String, items: { type: Array, default: () => [], }, }, }); </script>
Algolia方案实现提示
如果确定用Algolia,只需要把上面的filteredResults计算属性替换成接口请求逻辑即可:
- 安装algoliasearch依赖
- 初始化客户端、配置你的应用ID和搜索密钥、指定索引名
- 在handleInput方法中调用Algolia的搜索接口,将返回的结果赋值给本地的results变量,渲染即可,也可以直接使用官方封装的Vue InstantSearch组件,减少重复代码开发。
内容的提问来源于stack exchange,提问作者Alexandru Ana
相关产品推荐
相关产品推荐

