vue优雅的实现关闭弹框
原创背景
假如说,有这样一个页面,一个蒙层,然后上面一个弹框,怎么优雅的去做关闭这个弹框呢?
是的,怎么优雅的关闭这个弹框,是今天的主题。
1、点击 取消 , 确定 按钮,关闭弹框,的的确确,大多数是这样的做法,但是考虑到,用户有可能手指距离这里比较远,所以,操作可能会比较不方便,因此,这种体验似乎并不是很好,所以, 慢慢的用户就觉得需要点击蒙层的时候,也能关闭弹框 。
那么,怎么去实现点击蒙层关闭弹框呢?
1、找到蒙层那个div给蒙层加上 @click='closeDialog',因此,如果你的页面中有很多弹框, 那就意味着,你的页面有几个弹框,就要加几个click事件 ,就问你累不累,在加上取消,确定按钮,想必你肯定开始怀疑人生了。
2、使用全局方式,记得很久之前撸过jquery,jquery里面就一个live绑定事件的功能,大概就是
$(".dialog").live('click',function(){})
以上代码手撸,不保证可用,大概意思就是class为.dialog的element,都绑定一个这样的click事件,不管你当前在不在dom中,后面加进来的也是OK的,想想就觉得挺美好的,那么,可否在Vue中玩一玩呢?
遗憾的是,vue中可没有像jquery种selector的方式,两种框架的本质都不一样,vue中mvvm框架,如果需要用户去像jquery那样找element,本身就显得比较怪怪的,那么怎么办呢?可以这样玩。
document.body.addEventListener('click', event => {
const className = event.target.className
const classNameArray = ['tip-operating-layer', 'tip-dialog-wrap']
if (classNameArray.includes(className)) {
console.log('关闭浮层')
this.closeDialog()
})
我们直接给body绑定了一个click事件,然后event.target.className去比较class,如果是我们弹框的蒙层,就相应这个事件。
所以,你准备在每个页面都加上这一套代码是吗?
我想大多数人肯定是这样想的,难道你没发现,这段代码似乎和业务并没有任何关系,他只是检查是否点击了蒙层而已。因此,这段代码是可以下层的。
问题的关键是,怎么通知到页面去点击到了浮层这样一个事件,并作出相应的处理。
事件总线 在这个时候就起到作用了。
事件总线
const install = function(Vue) {
const eBus = new Vue({
methods: {
emit(event, ...args) {
this.$emit(event, ...args)
on(event, callback) {
console.info('...ebus on triggered...')
this.$on(event, callback)
off(event, callback) {
console.info('...ebus off triggered...')
this.$off(event, callback)
Vue.prototype.$ebus = eBus
export default install
你可能角色事件总线是什么很神秘的黑科技,但是我要告诉你的是,他事件上是一个全局单例而已,无非就是你把数据丢给我,我在把数据丢给这种数据的监听者而已,就比如上面这个插件,直接
Vue.use(ebus)
之后,就相当于Vue的原型链上有了这么一个bus的全局实例,嗯,唯一的。
所以,结合我们上面那个对蒙层点击的判断,就好说了
document.body.addEventListener('click', event => {
const className = event.target.className
const classNameArray = ['tip-operating-layer', 'tip-dialog-wrap']
if (classNameArray.includes(className)) {
this.$ebus.emit('closepop')
})
直接通过事件总线将这个消息发送给关注这个事件的页面,比如A页面。
created() {
this.$ebus.on('closepop', this.closeAllDialog)
beforeDestroy() {
this.$ebus.off('closepop')
},
此时具体的业务页面只需要关系我 closeAllDialog 做什么事情就好了,比如,无脑关闭是所有的弹框:
closeAllDialog() {
this.isOperationShow = false