【问题标题】:Ember view template as a computed propertyEmber 视图模板作为计算属性
【发布时间】:2012-12-08 10:03:46
【问题描述】:

当 Ember 视图是计算属性时,我在更新模板属性时遇到问题。

当视图首次加载并作为属性返回时,Ember 会正确编译模板,但稍后更改依赖项时模板计算的属性不会更新。

这是 JSFiddle 上的一个示例:http://jsfiddle.net/VkJC3/

App=Em.Application.create();

App.MyView = Em.View.extend({
    toggle: true
    ,template: function(){
        if (this.get('toggle')) {
            return Em.Handlebars.compile('toggle is true')
        } else {
            return Em.Handlebars.compile('toggle is false')
        }
     }.property('toggle')
});

theView= App.MyView.create();
theView.append('body');

Ember.run.later(function() {
    console.log('later');
    theView.set('toggle',false);
}, 2000);
​

对于如何完成此任务的任何其他建议表示赞赏。也许最好只将 if 助手放入一个车把模板中。

编辑:

这是一个更完整的示例,展示了包含上述 Ember.View 的 Ember.CollectionView:http://jsfiddle.net/VkJC3/6/

在 Ember.run.later 之后,第一项应该从类型 1 更改为类型 2,并更新计算的模板属性。

App=Em.Application.create();

App.MyView = Em.CollectionView.extend({
    content: [
        Em.Object.create({type: 1, data:"Maybe item type 1 is a link"})
        ,Em.Object.create({type: 2, data:"And item type 2 is a header"})]

    ,itemViewClass: Em.View.extend({
        template: function(){
            if (this.get('content.type')==1) {
                return Em.Handlebars.compile('<a href="#">{{view.content.data}}</a>')
            } else if (this.get('content.type')==2) {
                return Em.Handlebars.compile('<h1>{{view.content.data}}</h1>')
            }
         }.property('content.type')
    })
});


theView= App.MyView.create();
theView.append('body');

Ember.run.later(function() {
    console.log('later');
    theView.get('content')[0].set('type',2);
}, 2000);
    ​

【问题讨论】:

    标签: ember.js


    【解决方案1】:

    这不是您应该设置模板的方式。模板不应返回已编译的模板,而应充当已编译的模板。在您的代码中,您尝试将模板本身设置为计算属性,并且您正在有条件地编译两个可能的模板。恕我直言,您应该编译一个绑定到计算属性的模板,该属性根据您的切换属性评估文本,如下所示:

    App = Em.Application.create();
    
    App.MyView = Em.View.extend({
        template: Em.Handlebars.compile('toggle is {{toggleState}}'),
        toggle: true,
        toggleState: function(){
            if (this.get('toggle')) {
                return 'set to \'true\'';
            } else {
                return 'set to \'false\'';
            }
         }.property('toggle')
    });
    
    theView = App.MyView.create();
    theView.append('body');
    
    Ember.run.later(function() {
        console.log('later');
        theView.set('toggle',false);
    }, 2000);
    

    见小提琴here

    这只会更改需要更改的内容,因此您不必重新编译模板。

    编辑

    我对小提琴做了一些修改(你可以看到它here)。

    我在做什么,而不是直接分配 template 属性,我在创建应用程序之前将模板编译到 Ember.TEMPLATES 集合(我假设你无论如何都会在 prod 中做这样的事情),我正在更改您的计算属性以根据条件返回要使用的模板的名称(在您的情况下为content.type),并且我正在绑定该计算属性的templateName 属性。模板更改后,您拥有rerender 您的视图。代码可以改进,但我将在此处粘贴以演示解决方案:

    (function() {
    
        Em.TEMPLATES["one"] = Em.Handlebars.compile('<a href="#">{{view.content.data}}</a>');
        Em.TEMPLATES["two"] = Em.Handlebars.compile('<h1>{{view.content.data}}</h1>');
    
    })();
    
    App = Em.Application.create();
    
    App.MyView = Em.CollectionView.extend({
        content: [
            Em.Object.create({type: 1, data:"Item type 1 is a link"}),
            Em.Object.create({type: 2, data:"Item type 2 is a header"})
        ],
        itemViewClass: Em.View.extend({
            templateNameBinding: 'currentTypeName',
            currentTypeName: function() {
                if (this.get('content.type') == 1) {
                    return "one";
                } else if (this.get('content.type') == 2) {
                    return "two";
                }
            }.property('content.type'),
            templateNameObserver: function() {
                this.rerender();
            }.observes('templateName')
        })
    });
    // ... rest of the code... 
    

    就像我说的,这段代码可以改进......希望这会有所帮助

    【讨论】:

    • 感谢您的回复。我担心我的例子可能过于简化了我试图解决的问题。我想将示例视图用作 Ember.CollectionView 的 itemViewClass,它的内容数组中将包含 2 种或更多类型的项目。例如,一个列表集合视图包含:链接、标题和分隔符。然后每个项目将在 itemViewClass 上具有不同的模板,具体取决于该项目的内容。
    • 我不确定我是否理解。为什么需要将模板作为计算属性?
    • 我已经更新了上面的示例以在上下文中显示此问题。视图包含在 Ember.CollectionView
    • 酷,今晚晚些时候再看看
    • 刚刚看到这个更新。与观察者一起调用 rerender() 是这里缺少的部分。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2016-02-10
    • 2014-01-07
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    相关资源
    最近更新 更多