一、搜素效果如下:
二、核心
1)利用oninput属性来触发搜素功能
2)利用RegExp来对字符串来全局匹配关键字,利用replace方法来对匹配的关键字进行嵌入高亮的标签,最后利用v-html来嵌入html标签来达到关键字高亮显示
3)利用axios.CancelToken来终止上一次的异步请求,防止旧关键字查询覆盖新输入的关键字查询结果。
三、代码
1)HTML 搜索框部分绑定input事件(搜索框独立出来,作为一个基础组件(叫SearchToolbar.vue),嵌入到KnowledgeSearch.vue中)
<input type="text" class="input-search" placeholder="请输入搜索内容" v-model.trim="searchKey" @input="searchEvent" ref="searchInput" autocomplete="off" autocapitalize="off" autocorrect="off"/>
2)因为input绑定了输入监听事件@input,每一次输入值的改变,都会触发方法searchEvent(),尤其是在输入搜索关键字的时候,这种情况必然发生发送多次http异步请求,这样频繁地请求会导致流量损耗与性能下降。
如何解决?
我们利用setTimeout与clearTimeout元素,控制输入间隔为500ms,如果超过500s还没输入任何东西,就会向后端发送http异步请求。例如在搜索框种输入1,然后500ms过去之后,就会发送异步请求,如果在输入1之后的500ms输入值,例如我在499ms输入了值‘2’,那么上一次关键字为1的异步请求就会取消,进而进行关键字为‘12’的异步请求,并等待500ms。代码如下:
searchEvent() {
this.clearTimer();
if (this.searchKey && this.searchKey.length > 0) {
//获取当前延时函数的ID,便于后面clearTimeout清除该ID对应的延迟函数
this.timer = setTimeout(() => {
this.$emit('searchHandler', this.searchKey);
}, 500);
} else {
this.$emit('searchHandler', this.searchKey);
}
},
clearTimer() {
if (this.timer) {
clearTimeout(this.timer);
}
}
注意,你仔细想想,这里还存在一个漏洞。根据关键字发送异步http请求,假如在网络环境并不太好的情况下,异步请求可能经过2秒才返回关键字为‘成’的数据给我。然而,我在输入完关键字‘成’,超过500ms之后在输入‘龙’,那么之前的‘成’关键字的http异步请求已经发送给了服务器(要经过2s才返回数据给我。),而关键字为‘成龙’的http异步请求也发送过去了,它的响应时间是1s就返回数据。那么经过2s之后,得到的将会是关键字为‘成’的数据。因为最新的‘成龙’数据(1s)已经被‘成’数据(2s)所覆盖了。
3)利用axios.CancelToken来终止上一次的异步请求,防止旧关键字查询覆盖新输入的关键字查询结果。
import httpService from '@/services/HttpService';
4)v-html与Reg为搜索结果的关键字高亮显示
这一步是在展示数据的组件上做的。
4.1)HTML结果数据展示部分
4.2)js部分
import httpService from '@/services/HttpService';