1

什么是完全拆除并在旧位置重新实例化组件的最佳方法,最好是从模板中?

我们的用例是我们有一堆在我们的视图中使用的 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

这是一种体面的方法,还是我们认为这一切都错了?似乎必须有更好的选择,特别是因为在我们应用程序的一些地方是必要的。

4

1 回答 1

3

一种方法是使用reset()组件的方法来更改数据,并包含一个动态模板函数来选择合适的模板。data.type优点之一是除非更改,否则不需要重新渲染模板。(顺便说一句 - 默认组件不重新渲染背后的设计是,如果数据正在更新,则更新 DOM 值比重新渲染所有内容更有效。falsey-block 技巧可以强制刷新 - 但是可能并不总是需要)。

有很多特定于您的实现的细节,但是这个例子会给您一些想法:

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])
    }
})

如果在呈现各种模型的组件中存在共享逻辑或没有逻辑,则此方法有效。

通常,您希望为每种模型类型使用不同的组件,因为对于该特定模型,存在特定于该视图的观察者和事件处理程序。在这种情况下,此示例将动态提升到父级并为组件使用选项函数:

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] )
    }
})
于 2014-09-30T22:30:47.177 回答