之前用element-ui里面的dialog组件的时候,总是在给dialog绑定关闭函数的时候,before-close和close都绑定同一个,然后在里面做一样的事情,当时也没想过有什么区别,然后在里面通过以下手段来进行关闭,好像也能正常使用
js
// 二次封装组件
this.$emit("update:visible", false);
// 直接关闭
this.visible = false;
但是从来没有思考过这两个到底有什么区别,后来有一次弄懂了,知道了他们的区别,但今天又用到的时候我发现我又记不清了,于是专门写了这篇文章来帮助自己记忆。
首先我们先看看关于element-ui官方对于这两个东西的解释
Events
Attribute
其中before-close是我们传入的一个属性,而close和closed是绑定的事件。
这里官方文档说得不太清楚,before-close是关闭前的回调,但是只是通过右上角的X或者点击弹窗以外的部分关闭的时候会进行的处理
,同时在我们传入的这个函数调用的时候,会接收到一个回调函数,我们将其打印可以得到其内容
打印结果
我们可以看看源码
js
hide: function hide(cancel) {
if (cancel !== false) {
this.$emit('update:visible', false);
this.$emit('close');
this.closed = true;
}
},
这是element-ui\lib\dialog.js的相关代码
我们可以看到它接收一个参数,然后通过对该参数进行判断来执行相应的操作,当我们传入true的时候,首先会向父组件触发update:visible事件,并且更新父组件的vidible属性为false。
可以看看element-ui官方文档中dialog的相关事例代码
js
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
这里不理解update:visible是什么操作的可以去了解一下vue2中的.sync标识符
首先是触发了外部组件进行visible的更新,但是如果仅仅是通过更新visible来进行更新是无效的,因为外部并没有通过v-if或者v-show进行绑定,所以我们接下来可以看到dialog组件内部对于visible的监听
js
// 这里不知道是什么时候接收了外部声明的visible,看看有没有大佬解惑
watch: {
visible: function visible(val) {
var _this = this;
if (val) {
this.closed = false;
this.$emit('open');
this.$el.addEventListener('scroll', this.updatePopper);
this.$nextTick(function () {
_this.$refs.dialog.scrollTop = 0;
});
if (this.appendToBody) {
document.body.appendChild(this.$el);
}
} else {
this.$el.removeEventListener('scroll', this.updatePopper);
if (!this.closed) this.$emit('close');
if (this.destroyOnClose) {
this.$nextTick(function () {
_this.key++;
});
}
}
}
},
在第17行可以看到,如果此时弹窗是处于开启状态closed === false
时,会触发close事件
但是其实真正触发close事件的位置不是在这,我刚刚也踩坑了,发现是先执行了hide函数中的
this.closed = true
才执行的上面的这个函数,估计是因为emit或者watch的函数是异步执行的,等我有时间研究之后会专门讲一讲
在hide函数中接下来触发了close事件。那么一个流程就走完啦,你可能会好奇,那closed事件是什么时候执行的,我也好奇,于是我又看了一下,看到了这一段代码
js
afterLeave: function afterLeave() {
this.$emit('closed');
}
大致意思就是在动画结束之后执行,也就是触发了closed,至于它的实现,可以看看关于虚拟节点这块,刚刚瞄了一眼看到了。
所以真正的执行顺序应该是 before-close -> close -> closed
总结:
- before-close只有通过右上角的X和点击对话框以外区域来退出对话框的时候会触发
- close只有通过修改visible的值来进行弹窗关闭的时候会触发,当然before-close接收到的done函数本身也会触发
- 执行顺序:before-close -> close -> closed
- 通常情况下只需要绑定close和closed事件就足以满足我们的需求了,before-close如果不调用其中的done的函数的话貌似没有多大差别
如果有不对的,欢迎大佬指出!