# 如何实现一个高亮关键字的搜索框
正常思路是通过正则匹配改变关键字为标签,这里涉及到了防抖、正则和中文输入法的问题。
# 防抖
防抖是避免在同一时间执行多次相同函数。(在一段时间内多次执行了同一函数,以最后一次请求的参数执行function)
function debounce(func, wait = 300) {
var timeout;
return function () {
let context = this;
let args = arguments;
if(timeout) clearTimeout(timeout)
timeout = setTimeout(function() {
func.apply(context, args);
}, wait);
}
}
# 中文输入法
<input @input="input" type="text"/>
以上是一个input根据修改执行搜索的正常写法。但是这样写有个问题,输入中文期间也会去执行input
,输入中文会建立一个虚拟文本,最好是等用户确认之后再执行input
# 引入3个方法
- compositionStart: 用户切换中文输入法打拼音时会触发
- compositionUpdate: 输入拼音字母会触发
- compositionEnd: 最后将输入好的中文填入input中时触发
这3个方法是针对中文输入的,修改上面的页面内容
<input @compositionstart="compositionstart" @compositionend="compositionend" @input="input"/>
需要设置一个 bool
判断是不是正在输入值,避免输中文的时候也会调用 input
export default {
data() {
return {
list: [],
keyword: '',
isZh: false
}
},
methods: {
input(){
// input执行顺序不可控 setTimeout改变队列顺序
setTimeout(() => {
if(this.isZh) return;
console.log('input');
}, 0)
},
compositionend() {
this.isZh = false;
console.log('compositionend');
},
compositionstart() {
this.isZh = true;
console.log('compositionstart');
}
}
}
# 正则
通过正则修改返回的内容把关键字替换成标签返回。
export default {
data() {
return {
list: [],
keyword: '',
isZh: false
}
},
methods: {
input: debounce(function(){
if(this.isZh) return;
this.axios.get('/api').then(res => { // 模拟接口
this.list = res.data;
})
console.log('input');
}, 300),
compositionend() {
this.isZh = false;
console.log('compositionend');
},
compositionstart() {
this.isZh = true;
console.log('compositionstart');
}
},
computed: {
convertList() { // 返回转换后的数组
let {keyword} = this;
let reg = new RegExp(`${keyword}`);
return this.list.map(item => {
return item.replace(reg, `<b style="color: green;">${keyword}</b>`);
})
}
}
}
<div>
<input type="text" @compositionend="compositionend" @compositionstart="compositionstart" @onpaste="onpaste" @input="input" v-model="keyword">
<div v-for="item in convertList" v-html="item" :key="item"></div>
</div>
← pm2文档