2017-12-18 260 views
0

工作后我有一个嵌套的组件和子组件应接收来自主实例的参数,但问题是,我有打电话给事件两次获得参数。Vue2事件总线第二个电话

的index.html

<div id="app"> 
    <button @click="displayComponent">Display</button><br/><hr/> 
    {{ message }} 

    <mycomponent v-if="showComponent" @hide="hideComponents"></mycomponent> 
</div> 

code.js

window.bus = new Vue(); 

Vue.component('mycomponent', { 
    template: ` 
     <div> 
      <h3>Im the parent component</h3> 
      <childcomponent></childcomponent> 
      <button @click="$emit('hide')">Hide components</button> 
     </div> 
    ` 
}); 

Vue.component('childcomponent', { 
    template:` 
     <div> 
      <h4>Im the child component</h4> 
      <p>{{ data }}</p> 
     </div> 
    `, 

    data() { 
     return { 
      text: 'Nothing loaded' 
     }; 
    }, 

    methods: { 
     test() { 
      alert('hello'); 
     }, 

     getData(x) { 
      this.text = x; 
     } 
    }, 

    created(){ 
     bus.$on('extraCall', data => { 
      this.getData(data); 
      this.test(); 
     }); 
    } 
}); 

const app = new Vue({ 
    el: '#app', 

    data: { 
     message: 'hello world!', 
     showComponent: false 
    }, 

    methods: { 
     displayComponent() {   
      bus.$emit('extraCall', 'this is some extra text'); 
      this.showComponent = true; 
     }, 

     hideComponents() { 
      this.showComponent=false; 
     } 
    } 
}); 

子组件元件内的文本值被设置为默认值,显示按钮被点击后它触发bus.$emitextraCall事件与一些文本作为参数,这应该更新文本值,并且它只发生在第二次点击显示按钮后。

我缺少什么?

回答

1

<mycomponent>(及其子小孩<childcomponent>)由于v-if="showComponent"在单击显示按钮时未被实例化。

首先点击:

  1. extraCall发出总线上,但因此将其忽略没有监听该事件。
  2. <mycomponent>设置showComponent为true之后被实例化。
  3. <mycomponent>在其createdextraCall事件进行注册的监听器。

第二点击:

  1. extraCall发出总线上,并<mycomponent>处理它。

你可能会认为bus.$emit()this.showComponent = true行应该被交换,使<mycomponent>被之前实例化事件被发出,但这仍然无法工作,因为Vue公司推迟组件的创建,直到下一个microtask时该视图已更新。

这可能会实现:

displayComponent() { 
    this.showComponent = true; 

    // Wait for child component to be instantiated 
    this.$nextTick(() => { 
    bus.$emit('extraCall', 'this is some extra text'); 
    }); 
} 

如果上面的代码为你工作,我还是真的不推荐它虽然。在发布事件之前,您不需要考虑创建子组件(它将您的组件连接在一起)。您应该以其他方式共享数据,查看其他SO问题,了解跨组件共享数据的最佳方式。

+0

好的,这确实有用,但是正如你所说的不是最佳的,必须有更好的解决方案。但是,由于它解决了我作为解决方案进行投票的主要问题,如果我发现更好的方法将在此处发布。非常感谢! – deadPoet

+0

好吧,既然你真的很好,合作,我会问你这个问题,前一段时间我做了这样的工作,但它现在没有,我发现的唯一区别就是在html文件中,条件显示的组件,而不是V - 如果是V - 显示,当我改变它,只是工作...会使用这个任何抵押品损坏?... AFAIK V-SHOW需要更多的加载,但只是显示正确而v-if在每次调用时都会创建该组件。 – deadPoet

+1

'v-show'只切换元素上的样式。如果'v-show'为false,那么该组件仍然被创建,它因为样式而被隐藏(你可以在开发工具中看到它)。 'v-if'实际上会破坏/创建元素。如果您在此处使用'v-show'而不是'v-if',它将与您的原始代码一起工作。要决定'v-if'和'v-show',你需要考虑(1)你需要始终创建的元素吗? (2)会让隐藏在DOM中的元素影响任何':nth-​​child' CSS选择器? (3)用'v-show'保持元素的活性将使用更多的内存等。 –