VueJS Grandchild组件调用函数在Great grandparent组件中

use*_*145 4 vue.js

假设我有一个想要向一个曾祖父母发送消息的子组件,代码将是这样的,如果我错了,请纠正我:

Vue.component('child', {
  template: `<div v-on:click="clicked">Click me</div>`,
  methods: {
    clicked: function () {
        this.$emit('clicked', "hello")
    },
  },
});

Vue.component('parent', {
  template: `<child v-on:clicked="clicked"></child>`,
  methods: {
    clicked: function (msg) {
        this.$emit('clicked', msg)
    },
  },
});


Vue.component('grandparent', {
  template: `<parent v-on:clicked="clicked"></parent>`,
  methods: {
    clicked: function (msg) {
        this.$emit('clicked', msg)
    },
  },
});

Vue.component('greatgrandparent', {
  template: `<grandparent v-on:clicked="clicked"></grandparent>`,
  methods: {
    clicked: function (msg) {
        console.log('message from great grandchild: ' + msg);
    },
  },
});
Run Code Online (Sandbox Code Playgroud)

是否有可能直接拦截来自孩子的消息并调用曾祖父母中的点击功能而无需在每个父母处设置传递回调?

我知道我可以使用自定义数据总线,https: //vuejs.org/v2/guide/components.html#Non-Parent-Child-Communication,但由于我的组件已经有了亲子关系,我不应该能够以更简单的方式通知祖父母?

Roy*_*y J 8

如果你想保持封装,那就没有了.greatgrandparent不应该知道child.它知道grandparent,但不是有子组件或有多少.原则上,您可以将一个grandparentout的实现换成另一个没有多个层的实现.或者还有更多的层次child.你可以放入child一个顶级组件.

您已经了解了全球事件总线的概念.不过,公共汽车不一定是全球性的.你可以把它传递给道具链.(您可以将greatgrandparent自己用作公共汽车,但这会将其暴露给它的孩子;更好的卫生来制造真正的公共汽车.)

这将顶级组件与子组件区分开来:子组件将接收一个busprop来执行它有助于实现的顶级组件的功能.顶级组件将生成总线.

Vue.component('child', {
  template: `<div v-on:click="clicked">Click me</div>`,
  props: ['bus'],
  methods: {
    clicked: function() {
      this.bus.$emit('clicked', 'hello');
    },
  },
});

Vue.component('parent', {
  template: `<child :bus="bus"></child>`,
  props: ['bus']
});


Vue.component('grandparent', {
  template: `<parent :bus="bus"></parent>`,
  props: ['bus']
});

Vue.component('greatgrandparent', {
  template: `<grandparent :bus="bus" v-on:clicked="clicked"></grandparent>`,
  data() {
    return {
      bus: new Vue()
    };
  },
  created() {
    this.bus.$on('clicked', this.clicked);
  },
  methods: {
    clicked: function(msg) {
      console.log('message from great grandchild: ' + msg);
    },
  },
});

new Vue({
  el: '#app'
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<greatgrandparent id="app"></greatgrandparent>
Run Code Online (Sandbox Code Playgroud)