从父组件调用子组件中函数的最佳方式?
Best way to invoke a function in a child component from the parent?
我有一个活性组件,需要在用户要求时执行特定功能。也就是说,不是在初始化组件时,而是在之后的某个时间。
ractive docs mention events are used to communicate between components and their parents 但仅在事件从子项冒泡到父项的上下文中。在这种情况下,我们希望父级调用子级上的某些东西。
或者,还有 ractive.findComponent(),但示例似乎并没有太多地使用它来进行父子之间的交流。
我制作了以下使用 findComponent() 并有效的片段(点击 'Run Code Snippet' 然后 'Full Page').但是我不确定它是否最佳:
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>
从父组件调用子组件中函数的最佳方式是什么?
如果 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
原型上,因此只创建一次无论实例化了多少小部件。上下文绑定也没有内部问题。
我试图通过评论扩展@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>
按下按钮时,事件将冒泡到根实例,该实例具有任何 doCoolThing
事件的侦听器(使用普通和加星标的版本确保 any 除了根实例上的事件之外,嵌套组件还可以触发它)。唯一需要注意的是组件事件处理程序 (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 />
`
})
我有一个活性组件,需要在用户要求时执行特定功能。也就是说,不是在初始化组件时,而是在之后的某个时间。
ractive docs mention events are used to communicate between components and their parents 但仅在事件从子项冒泡到父项的上下文中。在这种情况下,我们希望父级调用子级上的某些东西。
或者,还有 ractive.findComponent(),但示例似乎并没有太多地使用它来进行父子之间的交流。
我制作了以下使用 findComponent() 并有效的片段(点击 'Run Code Snippet' 然后 'Full Page').但是我不确定它是否最佳:
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>
从父组件调用子组件中函数的最佳方式是什么?
如果 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
原型上,因此只创建一次无论实例化了多少小部件。上下文绑定也没有内部问题。
我试图通过评论扩展@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>
按下按钮时,事件将冒泡到根实例,该实例具有任何 doCoolThing
事件的侦听器(使用普通和加星标的版本确保 any 除了根实例上的事件之外,嵌套组件还可以触发它)。唯一需要注意的是组件事件处理程序 (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 />
`
})