完全拆除和重新安装旧组件的最佳方法是什么,最好是从模板中删除?
我们的用例是我们在视图中使用了一堆Backbone模型/集合。在init
中,我们可能会听一些模型或集合事件(有时很深),或者我们可能会针对该模型进行某种设置工作。看起来我们有两个选择:监听整个模型属性是否在视图上发生变化然后取消绑定任何事件并将它们绑定到新模型并重做任何设置工作,或强制视图拆除并在其位置放置一个新的使用新模型,因为模板可能会发生显着甚至完全变化。由于变化的重要性,我们选择了后一种路线,并确保我们从视图中的清晰平台开始。
到目前为止,我们一直在将条件包装在条件中并更改布尔值以强制拆除旧组件并重新渲染新组件:
HTML
<p>Some stuff that isn't bound to the model: {{prop1}}, {{prop2}}</p>
{{#if isRenderable}}
<myComponent model="{{model}}" />
{{/if}}
JS
component.set('isRenderable', false); // force `myComponent` to teardown
component.set('model', aDifferentModel); // this often happens in/via template
component.set('isRenderable', true); // force a new `myComponent` to render
这是一个不错的方法,还是我们看错了?似乎必须有更好的选择,特别是因为我们的应用程序中的一些地方是必要的。
答案 0 :(得分:3)
执行此操作的一种方法是使用组件的reset()
方法更改数据,并包含动态模板函数以选择适当的模板。其中一个优点是,除非data.type
发生更改,否则无需重新呈现模板。 (顺便说一下 - 组件不重新渲染的默认设计是,如果数据更新,更新DOM值比重新渲染所有内容更有效。假框块技巧可以强制刷新 - 但是可能并不总是需要。)
有很多细节专门针对您的实施,但this example会给您一些想法:
var Page = Ractive.extend({
template: function(data, t){
return data.type ? t.fromId(data.type) : 'loading...'
}
})
var r = new Ractive({
el: '#container',
template: '#template',
data: { model: datas.person1 },
components: {
page: Page
},
oninit: function(){
var page = this.findComponent('page')
this.observe('model', function(n){
page.reset(n)
})
},
load: function(load){
this.set('model', datas[load])
}
})
如果在呈现各种模型的组件中存在共享逻辑或没有逻辑,则此方法有效。
通常,您希望为每种模型类型使用不同的组件,因为有特定于该特定模型的视图的观察者和事件处理程序。在这种情况下,this example将动态提升到父级并使用组件的选项函数:
var r = new Ractive({
el: '#container',
template: '#template',
data: datas.person1,
components: {
page: function(data){
return components[data.type]
}
},
load: function(load){
this.reset( datas[load] )
}
})