从子组件中的父组件中侦听事件,并在没有集线器的情况下在vue中执行子组件的方法

时间:2017-09-01 12:38:00

标签: events event-handling vue.js vuejs2 vue-component

关于这个主题似乎有很多讨论,例如Stackoverflow answer using hubStackoverflow answer using refs,所以我真的想请专家提供一个明确简洁的答案来解决这个问题。如果答案也是不可能的,请说出来!

以下是该方案: 有两个组成部分,父母和孩子

<Parent> // There is a button here that can be clicked to emit an event using 'this.$emit()'
   <Child></Child> // The child listens and once hears the event, it does something
</Parent>

取得什么成果?

单击Parent中的按钮会发出某个事件,孩子会不断地听,一旦听到事件就会执行一个动作,比如调用自己的方法。

到目前为止有什么关于此的内容?

  1. 使用集线器,在Vue Hub中明确指出这是针对非 亲子沟通,那么使用它的意义何在 亲子沟通?

  2. 使用Refs,这是在无法使用道具和事件时作为最终解决方案提供的。那么为什么不能在第一时间举办活动?

  3. 我自己的想法

    在我看来,一个事件的发射和听取它只能从孩子到父母,基本上是单向沟通。父节点能够发出事件,但子组件无法捕获事件。为什么?我试过这个并没有用:

    在我拥有的父组件中(通过单击父组件中的按钮触发):

    methods: {
      generateCharts: function () {
        this.$emit('generate-charts')
        console.log('charts generated')
    }
    

    在子组件中我有:

    mounted () {
     this.parent.$on('generate-charts', function () {
       console.log('event captured') // Here nothing gets logged to the console
     })
    }
    

    更新

    刚刚发现了这个答案Vue $emit。 显然这对于​​Vue来说根本不可能。

    在第一个例子中,它似乎是一个缺陷,因为我曾经遇到过几种情况,我需要从父母那里开一个事件并在孩子身上听。

    我可以想象必须有一个原因,为什么Vue无法做到这一点,这可能是一个设计考虑因素,Vue专家解释了为什么会出现这种情况,以及什么是更好的设计方法来解决一般情况下通过从父母到孩子的活动,将非常感激。

1 个答案:

答案 0 :(得分:1)

答案是使用道具并对这些道具的变化做出反应。一开始习惯这有点令人困惑,因为看起来很多代码要做一些简单的事情,但随着你的应用程序变得越来越复杂,使用道具强制执行数据流的方式确实有助于调试和推理代码试图完成的任务。

例如,一个模态。您的父级单击按钮设置showChildModal = true,此值将作为道具传递给子级。孩子正在观察道具的变化,当它看到它设置为真时它会打开模态。最后,当模式关闭时,父级正在查看的子级$emit('close')以及当它看到它设置showChildModal = false

&#13;
&#13;
Vue.component('child', {
  template: '#child',
  props: ['showModal'],
  name: 'child',
  watch: {
    showModal: function(show) {
      if (show) {
        window.setTimeout(() => {
          if (window.confirm("Hi, I'm the child modal")) {
            this.$emit('close');
          } else {
            this.$emit('close');
          }
        }, 100)
      }
    }
  }
})

var vm = new Vue({
  el: '#el',
  data() {
    return {
      showChildModal: false
    }
  }
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="el">
  Parent
  <p>
    <button @click="showChildModal = true">Click to show child modal</button>
  </p>
  <hr>
  <p>
    <child :show-modal="showChildModal" v-on:close="showChildModal = false"> </child>
  </p>
</div>

<script type="x-template" id="child">
  <div>
    Child
    <p>
      modal open? {{ showModal }}
    </p>
  </div>
</script>
&#13;
&#13;
&#13;