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

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

<div class="inputWrapper" @click="showOptions = !showOptions">
<input type="text" readonly placeholder="请选择菜品" :value="selected"> //这里用value绑定一个data值selected
<span class="iconfont icon-zhankaishangxia"></span>
</div>
<ul class="options" v-show="showOptions">
<li v-for="(item, index) in options" :key="index" @click="choose(item.value)">{{item.value}}</li>
</ul>
......
data() {
return {
......
showOptions: false
selected: ''
}
},
methods: {
choose(value) {
this.showOptions = false
if (value !== this.selected) {
this.selected = value
}
}
}

逻辑很简单,在input里用value绑定一个data值,点击选择某个选项后,将选项的内容赋给这个data值即可,同时,隐藏整个选项内容。

效果如下:

 

从上面的效果图中可以看到,已经可以正常选择了,但是有一个问题,就是它选项内容展示的时候,我们希望点击其它空白的地方也可以让选择内容隐藏,但是上面的代码并没有解决这个问题,接下来我们来用两种办法来解决它。

3、常规的DOM操作 VS Vue自定义指令

其实,实现这个功能并不难,只是要想解决它就需要操作DOM


<div class="inputWrapper" @click.stop="showOptions = !showOptions"> //注意这里的stop修饰器
<input type="text" readonly placeholder="请选择菜品" :value="selected">
<span class="iconfont icon-zhankaishangxia"></span>
</div>
<ul class="options" v-show="showOptions">
<li v-for="(item, index) in options" :key="index" @click.stop="choose(item.value)">{{item.value}}</li> //还有这里的stop修饰器
</ul>
...
data() {
return {
......
showOptions: false
}
}
mounted() {
let that = this
document.addEventListener('click', function() {
that.showOptions = false
})
}

上面的代码有两点:一个是在mounted后面给整个document添加了点击事件,这样在点击时候就可以将options隐藏,但是,我们在点击输入框部分和选项内容时,我们不希望它触发,而是让它走我们之前写好的逻辑,所以给两个 click 事件都添加了 stop 修饰器来阻止冒泡,这样,点击到它们的时候就不会冒泡到 document 上面了。效果如下:

 

到这里基本功能都写完了,可以通过添加 $emit 和 props 来进行数据传递,让它更加通用些。但是最后关于点击其它地方让选项部分消失的功能,我们还可以再完善下,可以考虑使用Vue指令的方式实现。