自定义指令
使用组件库的时候,有的 props
属性直接传属性名称就可以达到效果,一直以为是用指令写的,最近测试了一下,发现其实针对类型为 Boolean
的 props
属性,传 props
属性名就已经表示将这个属性设为 true
,其他类型的 props
属性这样传会报错的。
正文
可以通过属性名 directives
编写全局 / 组件指令
和组件、页面一样,指令也有钩子函数
bind
只调用一次,指令第一次绑定到元素上时调用。用于初始化
inserted
元素插入父节点时调用
update
组件 VNode
更新时调用,此时子 VNode
不一定更新完
componentUpdated
组件 VNode
和子 VNode
都更新完后调用
unbind
只调用一次,指令和绑定元素解绑时调用
钩子函数中有以下几个参数
el
绑定指令的 dom 元素
binding
指令的详细信息 name, value, oldValue, expression, modifier, arg...
其中
modifier
是指令修饰符,例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
arg
指令参数,非常灵活,动态指令中常常用到,例如v-my-directive:[position]="30"
传递位置参数left right...
表示要偏离30px
的方向
vnode
当前虚拟节点
oldVnode
上一个虚拟节点,仅在 update
和 componentUpdated
钩子中可用
使用场景:搜索结果高亮搜索关键词
// 使用方法 v-emphasize="searchKey"
directives: {
emphasize: {
inserted (el, binding) {
// 搜索关键词通过 value 传递
const { value } = binding
if (value) {
// 根据 关键词 分割
let list = el.innerText.split(value)
if (list.length === 0) {
return
}
let res = document.createElement('span')
while (list.length > 1) {
// 构造高亮 span
const span = document.createElement('span')
span.setAttribute('style', 'color: red')
span.textContent = value
// 添加 非高亮 和 高亮部分
res.appendChild(document.createTextNode(list.shift()))
res.appendChild(span)
}
// 处理 list 的最后一个元素
res.appendChild(document.createTextNode(list.shift()))
// el.firstChild.remove()
// el.append(res)
// 移除 span 原来的 子元素
// 添加 构造的元素
el.firstChild.replaceWith(...res.childNodes)
}
},
},
},
因为会对 dom
进行操作,所以一定不要直接在这个 dom
上面绑定其他的操作,建议在外面包一层 div
来绑定事件处理和样式