接到一个令人抓狂的需求:
在搜索框输入关键字搜索时,搜索的结果需要对该关键字做匹配并高亮显示,这是非常简单的。然而给我的需求并不是这么简单的,而是需要`input`的输入框的文本高亮,这里是用了`elementUI` 的`el-cascader`级联选择器,
其实`el-cascader`的底层就是一个`input`。
直接上最终效果图
最终效果图
一开始就想用过滤器实现,vue1.0支持过滤器,2.0取消了,官网说用computed,个人理解这里使用computed就需要定义get和set方法,否则双向绑定就会失效,这对于大数据量的时候无疑是行不通的,于是调整思路
解决思路:
过滤器行不通,那就用指令实现之
1、自定义指令获取绑定指令的`node`节点
2、正则匹配需要高亮的文本,用`<span>`标签包裹,`<span>`里写样式
3、将该节点的`innerHTML = <span></span>`
思路有了,直接上代码:
Vue.directive('highlight', {
// 这里的 el 就是被注册指令的 node 节点, binding 就是节点信息,
// 包括一个 value,就是传进来的数据
// vnode 就是 vue 虚拟节点
// 刚刚注册这个事件,就使用 bind
bind(el, binding, vnode) {
const {
value
} = binding;
if (value && typeof value === 'object') {
const {hWord, word} = value;
el.innerHTML = word.replace(new RegExp(hWord, 'ig'), (a) => {
return `<span style="color: #F5453B">${a}</span>`
});
}
},
// 绑定的数据更新了,执行 update
update(el, binding, vnode) {
const {
value
} = binding;
if (value && typeof value === 'object') {
const {hWord, word} = value;
el.innerHTML = word.replace(new RegExp(hWord, 'ig'),
(a) => `<span style="color: #F5453B">${a}</span>` );
}
}
})
指令使用:
在需要高亮的地方直接使用,传入一个对象参数
v-highlight="{hWord:搜索关键字, word: 需要被高亮的文本}"
这样就实现input的文本高亮了(`el-selet`,普通`input`)同理
但是由于我这里是使用里`el-cascader`,以上的代码虽然是实现里,但是指令中使用里`innerHTML`,会将组件的icon覆盖掉了,我想了一个比较挫的解决办法
就是在组件的外面用一层div包裹,在该div上使用指令,将组件的`input`的`height`设为0,其实就是隐藏了`input`。
到此大功告成。。。