资讯专栏INFORMATION COLUMN

Vue2.0父子组件间事件派发机制

xietao3 / 3516人阅读

摘要:从过来的都知道,在中,父子组件间事件通信的和被移除了。通过广播和事件分发的机制,就显得比较混乱了。在父组件中中然后,在子组件中,主要在任意事件回调中使用来触发自定义的事件,后面还可以加上参数传给父组件。

从vue1.x过来的都知道,在vue2.0中,父子组件间事件通信的$dispatch$broadcase被移除了。官方考虑是基于组件树结构的事件流方式实在是让人难以理解,并且在组件结构扩展的过程中会变得越来越脆落。特别是在组件层级比较深的情况下。通过广播和事件分发的机制,就显得比较混乱了。

官方在废除的同时,也为我们提供了替换方案,包括实例化一个空的vue实例,使用$emit反应子组件上的状态变化

1.使用$emit触发事件

helloWorld.vue作为父组件,dialogConfigVisible变量控制子组件弹框显示或隐藏。
configBox.vue作为子组件,假设为封装的公告弹窗。

在父组件中 helloWorld.vue 中

< template/>

    

script

  data(){
    return {
      dialogConfigVisible:true
    }
  }
   methods: {
     changeConfigVisible(flag) {
         this.dialogConfigVisible = flag;
     }
   }

然后,在子组件 configBox.vue 中,主要在任意事件回调中,使用 $emit来触发自定义的 listenToConfig事件,后面还可以加上参数传给父组件。比如,在子组件弹窗上点击×关闭时,通知父组件 helloWorld.vue我要关闭了,主要方便父组件改变相应状态变量,并传入false到自定义的事件中。

script

methods:{
  dialogClose() {
    this.show = false;
    this.$emit("listenToConfig", false)
  }
}

在子組件中,主动触发listenToConfig事件,并传入参数 false, 告诉父组件 helloWorld.vue对话框要关闭了。这里就可以避免父组件中的状态未变化,再次刷新页面的时候对话框会自动出现。

2.实例化一个空的vue实例bus

这里实例化一个bus 空vue实例,主要为了统一管理子组件和父组件相互通信,通过bus 作为媒介,
首先新建一个bus.js 文件,在里面新建一个对象,父组件为table.vue, 子组件为tableColumn.vue

  // bus.js
 import Vue from "vue";
 export var bus = new Vue({
     data:{
       scrollY:false
     },
     methods:{
        updateScrollY(flag){
          this.scrollY = flag;
        }
     }
   })

然后分别引入:

 // table.vue
 

  // tableColumn.vue
  

上面的父子组件中,父组件中利用bus注册监听事件getData,子组件中一旦有状态变化,就触发bus上对应的事件。

这种利用空实例的方式,相当于创建了一个事件中心,所以这种通信同样适用于非父子组件间的通信,

3.多级父子组件通信

有时,可能想要实现通信的两个组件不是直接的父子组件,而是祖父和孙子,或者是跨越了更多层级的父子组件

不可能由子组件一级一级的向上传递参数,来达到通信的目的,虽然现在我们理解的通信都是这样经过中转的。可以通过while等循环,不断向上遍历,直到找到目标父组件,就在对应的组件上触发事件。

下面就只element-ui实现的一个父子组件通信的mixins,对于组件同步有很大的作用。在element-ui 的优点概述中也特意提到这个组件通信

function broadcast(componentName, eventName, params) {

  // 向下遍历每个子节点,触发相应的向下广播的 事件
  this.$children.forEach(child => {
    var name = child.$options.componentName;

    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.apply(child, [componentName, eventName].concat([params]));
    }
  });
}
export default {
  methods: {
     // 向上遍历父节点,来获取指定父节点,通过$emit 在相应的 组件中触发 eventName  事件
    dispatch(componentName, eventName, params) {
      var parent = this.$parent || this.$root;
      var name = parent.$options.componentName;
      // 上面的componentName 需要在每个vue 实例中额外配置自定义属性 componentName,
      //可以简单替换成var name = parent.$options._componentTag;

      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent;

        if (parent) {
          name = parent.$options.componentName;
        }
      }
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    },
    broadcast(componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params);
    }
  }
};

首先定义两个嵌套的组件 f1.vue 和 c1.vue,实例是:

 
   
 

然后,分别定义两个父子组件:

c2.vue

 
 f1.vue



这样,就可以在子组件中点击按钮,触发 listenerToC1事件,在父组件中监听到这个事件,
其实更$emit触发事件类似。不同之处在于,这里可以多级嵌套,不一定是直接的父子组件都可以触发到。

4 .sync 修饰符

在Vue1.x中,利用prop进行"双向绑定",实现父子组件通信,都会用到.sync修饰符,可以将子组件中对应的prop值变化同步到父组件中。但是,这样就破坏了单向数据流,在2.0版本中被移除了,在2.3.0版本中又以一种语法糖的形式加了进来。
可以看下文档上给出的实例

   

被扩展为

  

其实跟本文中第一种方法基本一致,更加简化了。

同样helloWorld.vue作为父组件, configBox.vue作为子组件,

      

然后在子组件中,显式的触发更新事件:

methods:{
  dialogClose() {
    this.show = false;
    this.$emit("update:visible", false)
  }
}

这样visible 的变化就能同步到父组件中了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90697.html

相关文章

  • vue2.0组件事件派发与接收

    摘要:官方给出的最简单的升级建议是使用集中的事件处理器而且也明确说明了一个空的实例就可以做到因为实例实现了一个事件分发接口在中在初始化之前,给添加一个名字为的空对象某一个组件内调用事件触发另一个组件内调用事件接收在组件销毁时接除事件绑定使用方法 在vue的开发中,经常会在两个组件间进行事件的通信 在vue1.0中我们使用$dispatch 和 $broadcast child.vue: th...

    luckyw 评论0 收藏0
  • vue2.0组件事件派发与接收

    摘要:官方给出的最简单的升级建议是使用集中的事件处理器而且也明确说明了一个空的实例就可以做到因为实例实现了一个事件分发接口在中在初始化之前,给添加一个名字为的空对象某一个组件内调用事件触发另一个组件内调用事件接收在组件销毁时接除事件绑定使用方法 在vue的开发中,经常会在两个组件间进行事件的通信 在vue1.0中我们使用$dispatch 和 $broadcast child.vue: th...

    JayChen 评论0 收藏0
  • vue2.0组件事件派发与接收

    摘要:官方给出的最简单的升级建议是使用集中的事件处理器而且也明确说明了一个空的实例就可以做到因为实例实现了一个事件分发接口在中在初始化之前,给添加一个名字为的空对象某一个组件内调用事件触发另一个组件内调用事件接收在组件销毁时接除事件绑定使用方法 在vue的开发中,经常会在两个组件间进行事件的通信 在vue1.0中我们使用$dispatch 和 $broadcast child.vue: th...

    My_Oh_My 评论0 收藏0
  • 聊聊Vue.js组件通信的几种姿势

    摘要:子组件向父组件通信方法一使用事件父组件向子组件传递事件方法,子组件通过触发事件,回调给父组件。非父子组件兄弟组件之间的数据传递非父子组件通信,官方推荐使用一个实例作为中央事件总线。 写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出。 文章的原地址:https://github.com/answ...

    Profeel 评论0 收藏0

发表评论

0条评论

xietao3

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<