使用Vue自定义指令实现Select组件

2020-06-14 06:29:43易采站长站整理

从上面的图片可以看出当指令和元素绑定的时候即 bind 的时候,它会执行bind函数获得很多有用的东西,上面我们讲了 bind 函数里有几个重要的参数,从打印出的结果里我们非常清楚地看到,el就是指令绑定的元素本身,binding是一个对象,它获得了很多有用的东西,包括传递进来的函数。

明白了它的基本构造,我们就来继续完善这个指令。


<ul class="options" v-show="showOptions" v-clickOut="test">
<li v-for="(item, index) in options" :key="index" @click.stop="choose(item.value)">{{item.value}}</li>
</ul>
...
methods: {
test() {
this.showOptions = false
}
},
directives: {
clickOut: {
bind: function(el, binding) {
document.addEventListener('click', function(e) {
if (el.contains(e.target)) return false
if (binding.expression) {
binding.value()
}
})
}
}

看下上面改写过的代码做了些啥? 说下逻辑:当我们自定的 v-clickOut 与选项部分的ul元素绑定的时候,我们监听document的click事件,如果点击的元素是被指令绑定的元素的子元素或是被绑定元素本身,那就什么都不做;如果不是,那就执行传递进来的test函数。而test函数执行的结果就是把选项部分隐藏。

逻辑很清楚。

当然我们可以继续完善它。我们给

document.addEventListener 
了,也可以在 合适的时候
removeEventListener 
,这个合适的时候就是 unbind 钩子函数。

所以我们可以完善下:


......
directives : {
clickOut: {
bind: function(el, binding) {
function handler(e) {
if (el.contains(el.target)) return false
if (binding.expression) {
binding.value()
}
}
el.handler = handler
document.addEventListener('click', el.handler)
},
unbind: function(el) {
document.removeEventListener('click', el.handler)
}
}
}

代码如上,效果如下:

 

简单总结一下:这是一个非常简单的小例子,因为需要操作DOM,所以我们选择使用自定义来完成,当然我们也可以使用其它方法。只是,在我们用Vue的时候,如果遇到需要操作DOM的时候,那么可以想想可不可以通过自定义指令来实现呢!