2017-12-18 270 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'保持元素的活性將使用更多的內存等。 –