1

我有几个不同的问题,我希望这个例子很容易理解。该代码使用默认隐藏元素的 HTML 模板(使用 CSS)。主干视图使用模型中的数据来显示适当的值,或者如果模式中没有值,则隐藏 UI 元素。

给定一个默认隐藏所有内容的模板(使用 CSS),例如:

<script type="text/template" id="Person-Template">
    <span class="fname" title="FirstName"></span>
    <span class="lname" title="LastName"></span>
    <span class="age" title="Age"></span>
</script>

要隐藏每个 UI 元素,CSS 是:

span.fname,
span.lname,
span.age {
    display:none; 
}

因此,我的 Backbone.js 模型将是:

PersonModel = Backbone.Model.extend({
        defaults: {
            fname: undefined,
            lname: undefined,
            age: undefined
        }
    });

视图(简化)将是:

PersonView = Backbone.View.extend({
    tagName: 'div',

    initialize: function() {
        this.model.on("fname", this.updateFName, this);
        this.model.on("lname", this.updateLName, this);
        this.model.on("age", this.updateAge, this);
    },

    updateFName: function() {
        // Pseudo code 
        Get 'new' value from Model
        Obtain reference to DOM element span.fname
        Update span.fname

        if (model value is empty) {
           Hide UI element.
        }
    },

    updateLName: function() {
        // Same as above
    },

    updateAge: function() {
        // Same as above
    },

    render: function() {
        // Get model values to display
        var values = {
            FirstName : this.model.get('fname'),
            LastName : this.model.get('lname'),
            Age: this.model.get('age'),
        };

        // Load HTML template
        var template = $('#Person-Template').html();

        // Populate template with values
        var t = _.template(template, values);

       // Show / hide UI elements
       this.updateFname();
       this.updateLName();
       this.updateAge();
    }

}

最后,问题是:从 render() 调用每个 updateXYZ() 方法只是为了确定 UI 元素应该设置为隐藏还是可见,这似乎很不自然。我的模型中有很多属性,代码看起来真的有点荒谬。

有人告诉我,视图不应该负责确定应该或应该显示什么。我的问题是,那么什么是负责任的?用户可能会执行一些(有效的)aciton 来清除名字,在这种情况下,我不希望我的视图显示“名字:”后跟没有值。

4

1 回答 1

3

首先,您不需要values手动构建,只需使用toJSON

var values = this.model.toJSON();

然后,您必须将您填写的模板添加到您的视图中el

this.$el.html(_.template(template, values));

并且您的模板可能应该包含要在模板中显示的内容:

<script type="text/template" id="Person-Template">
    <span class="fname" title="FirstName">F: <%= fname %></span>
    <span class="lname" title="LastName">L: <%= lname %></span>
    <span class="age" title="Age">A: <%= age %></span>
</script>

您不需要为这三个部分中的每一个分开功能,您可以在您的 : 中循环遍历它们render

_(values).each(function(v, k) {
    var m = _(v).isUndefined() ? 'hide' : 'show';
    this.$('.' + k)[m]();
}, this);

现在回到你的活动。"fname"除非您添加了自定义事件,否则没有事件之类的东西。但是没必要这样,模型会在改变时触发"change""change:fname"事件fname;你只需要关心"change"

initialize: function() {
    _.bindAll(this, 'render');
    this.model.on("change", this.render);
},

我还render使用绑定到您的视图实例,_.bindAll这样您就不必担心this.model.on.

现在你有了一些有用的东西:http: //jsfiddle.net/ambiguous/46puP/


您还可以将“应该显示”逻辑推送到模板中:

<script type="text/template" id="Person-Template">
    <% if(fname) { %><span class="fname" title="FirstName">F: <%= fname %></span><% } %>
    <% if(lname) { %><span class="lname" title="LastName">L: <%= lname %></span><%  } %>
    <% if(age)   { %><span class="age" title="Age">A: <%= age %></span><%           } %>
</script>

并简化您的render

render: function() {
    var values   = this.model.toJSON();
    var template = $('#Person-Template').html();
    this.$el.html(_.template(template, values));
    return this;
}

演示:http: //jsfiddle.net/ambiguous/W9cnJ/

这种方法可能是最常见的,它没有任何问题。我认为您误解了先前的答案试图告诉您的内容。模板已经选择了要显示的信息,<%= ... %>因此没有充分的理由不应该查看fname,例如,在尝试显示之前是否已设置。根据数据的性质,您可能希望if(!_(fname).isUndefined())在模板中使用等,但简单的真实性检查可能没问题;在某些情况下这age可能是一个问题,因此您可能希望对此更加严格。

于 2012-06-30T17:33:48.273 回答