2016-11-17 25 views
0

我有一個ractive組件需要執行一個特定的功能,當用戶要求。也就是說,不是在組件初始化時,而是在一段時間之後。從父級調用子組件中的函數的最佳方法?

ractive docs mention events are used to communicate between components and their parents但只限於從孩子向父母冒泡的事件。在這種情況下,我們希望父母在孩子上調用某些東西。

另外,還有ractive.findComponent(),但這些例子似乎並沒有太多用於從父母傳遞給孩子。

我做了下面的代碼片段,它使用findComponent()和工程(點擊「運行代碼片段」然後「整頁顯示」)。但是我不知道它是最理想的:

var coolWidget = Ractive.extend({ 
 
    data: {}, 
 
    template: `<span>Your favorite fruit is {{ fruit }}</span>`, 
 
    data: function(){ 
 
    return { 
 
     fruit: 'banana', 
 
     doCoolThing: function(){ 
 
     var component = this; 
 
     console.log('Going to change fruit...') 
 
     setTimeout(function(){ 
 
      component.set('fruit', 'avocado') 
 
     }, 3 * 1000) 
 
     } 
 
    } 
 
    } 
 
}) 
 

 
var ui = new Ractive({ 
 
    el: '.some-ui', 
 
    data: { name: 'Mike'}, 
 
    components: { 
 
    coolWidget 
 
    }, 
 
    template: ` 
 
    <h1>Hello {{ name}}</h1> 
 
    <button>Press me</button> 
 
    <coolWidget /> 
 
    `, 
 
    oncomplete: function(){ 
 
    var widget = this.findComponent('coolWidget') 
 
    document.querySelector('button').addEventListener('click', function(){ 
 
     widget.get('doCoolThing')(); 
 
    }) 
 
    } 
 
})
<script src="http://cdn.ractivejs.org/latest/ractive.js"></script> 
 
<div class="some-ui"> 
 

 
</div>

什麼是最好的方式調用一個函數從父項的子組件?

回答

1

如果doCoolThing是一個頂級選項...

var coolWidget = Ractive.extend({ 
    data: {}, 
    template: `<span>Your favorite fruit is {{ fruit }}</span>`, 
    data: function(){ 
    return { 
     fruit: 'banana' 
    } 
    }, 
    doCoolThing: function(){ 
    var component = this; 
    console.log('Going to change fruit...') 
    setTimeout(function(){ 
     component.set('fruit', 'avocado') 
    }, 3 * 1000) 
    } 
}) 

...那麼你就可以調用該方法,像這樣:

oncomplete: function(){ 
    var widget = this.findComponent('coolWidget') 
    document.querySelector('button').addEventListener('click', function(){ 
    widget.doCoolThing(); 
    }) 
} 

這不只是感覺更好的是,它實際上有一個實際的好處 - doCoolThing坐在coolWidget原型,所以只有創建一次,無論有多少小部件實例化。也沒有內部使用上下文綁定。

2

我正試圖擴展@ rich-harris回答評論,但顯然這太長了。

如果你想有ractive管理佈線多一點,你可以訂閱從根實例和火災事件:

在小部件的OnRender:this.coolThingListener = this.root.on('doCoolThing *.doCoolThing', function() { /* cool thing here */ })

在小部件onunrender:this.coolThingListener.cancel()

在主要實例模板中:<button on-click="doCoolThing">Press me</button>

當按鈕被按下時,事件將冒泡到根實例,該實例具有用於任何的偵聽器事件(使用普通和星號版本確保任何嵌套組件除了根實例上的事件外還可以觸發它)。唯一需要注意的是組件事件處理程序(coolThingListener)中的this將作爲根實例,因此您需要捕獲組件引用或使用箭頭函數。

onunrender中存在取消訂閱的情況,以防萬一您在根的整個生命週期中出現了多個組件實例。

這裏的整個事情:

var coolWidget = Ractive.extend({ 
    data: {}, 
    template: `<span>Your favorite fruit is {{ fruit }}</span>`, 
    onrender: function(){ 
    var component = this; 
    // if 'doCoolThing' might fire from another component, add '*.doCoolThing' to listener to matching child component events too 
    this.coolThingListener = this.root.on('doCoolThing', function(){ 
     component.doCoolThing(); 
    }); 
    }, 
    onunrender: function(){ 
    this.coolThingListener.cancel(); 
    }, 
    data: function(){ 
    return { 
     fruit: 'banana' 
    } 
    }, 
    doCoolThing: function(){ 
    console.log('Going to change fruit...') 
    setTimeout(function(){ 
     this.set('fruit', 'avocado') 
    }, 3 * 1000) 
    } 
}) 

var ui = new Ractive({ 
    el: '.some-ui', 
    data: { name: 'Mike'}, 
    components: { 
    coolWidget 
    }, 
    template: ` 
    <h1>Hello {{ name}}</h1> 
    <button on-click="doCoolThing">Press me</button> 
    <coolWidget /> 
    ` 
}) 
+0

謝謝! 「doCoolThing * .doCoolThing」正確嗎?難道它不像'coolWidget doCoolThing'嗎? – mikemaccana

+0

@mikemaccana在這個特定的情況下,你可以放棄'* .doCoolThing',因爲事件源於根,不會被命名空間。如果它可能來自子組件,那麼星型偵聽器會捕獲它,因爲事件在第一次跨越組件邊界(氣泡到其直接父級)時會增長名稱空間。用空格分隔多個名稱只是訂閱多個事件的簡寫。 –

+0

你能否更新你的例子以符合你的評論?這會讓它更清晰一些。你也可以使用addEventListener()來進行事件綁定,而不是使用HTML嗎? – mikemaccana

相關問題