src/mixins/emitter.js中有两个方法:dispatch和broadcast,这两个方法在多处用到:
例如 在packages/select/src/select.vue中,value的监控方法中用到dispatch和broadcast:
watch: {
value(val, oldVal) {
if (!valueEquals(val, oldVal)) {
this.dispatch('ElFormItem', 'el.form.change', val);
}
},
visible(val) {
if (!val) {
this.broadcast('ElSelectDropdown', 'destroyPopper');
}
}
}
一、dispatch(子组件发送消息给上层组件)
dispatch(componentName, eventName, params) {
// 当前父组件
var parent = this.$parent || this.$root;
// 当前父组件的组件名
var name = parent.$options.componentName;
// 通过$parent,一直向上找,直到组件名等于componentName
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.componentName;
}
}
if (parent) {
// 如果找到目标组件,那么调用目标组件的$emit方法
parent.$emit.apply(parent, [eventName].concat(params));
}
}
还是以packages/select/src/select.vue为例:
<el-form>
<el-form-item>
<el-select>
</el-select>
</el-form-item>
</el-form>
<meta charset="utf-8">
el-select组件中调用dispatch
方法(this.dispatch('ElFormItem', 'el.form.change', val)
),通过while循环,找到上层名为ElFormItem的组件,并在上层组件实例中
on方法捕获该事件:
addValidateEvents() {
......
if (rules.length || this.required !== undefined) {
......
this.$on('el.form.change', this.onFieldChange);
}
}
二、broadcast(上层组件通知下层组件)
function broadcast(componentName, eventName, params) {
// 遍历所有子组件
this.$children.forEach(child => {
var name = child.$options.componentName;
// 找到组件名为componentName的子组件,并调用该子组件的$emit方法;
// 否则,继续递归
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
broadcast.apply(child, [componentName, eventName].concat([params]));
}
});
}
还是以packages/select/src/select.vue为例:
<el-select>
<el-option></el-option>
<el-option></el-option>
</el-select>
el-select组件中调用broadcast方法:
handleQueryChange(val) {
......
this.broadcast('ElOption', 'queryChange', val);
......
}
上面代码,会向所有el-option子组件广播queryChange事件并携带数据,在el-option组件的created方法中会通过$on方法响应:
created() {
......
this.$on('queryChange', this.queryChange);
......
}
网友评论