Backbone.js-视图和模型之间的关系?

Backbone.js-视图和模型之间的关系?,backbone.js,Backbone.js,我有一些不同的问题,我希望这个例子很容易理解。代码使用HTML模板,默认情况下隐藏元素(使用CSS)。主干视图使用模型中的数据显示适当的值,如果模式中不存在值,则隐藏UI元素 给定一个默认情况下隐藏所有内容的模板(使用CSS),例如: <script type="text/template" id="Person-Template"> <span class="fname" title="FirstName"></span> <span

我有一些不同的问题,我希望这个例子很容易理解。代码使用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>
因此,我的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元素应该设置为hidden还是visible,这似乎有点骇人听闻。我的模型中有很多属性,代码看起来真的有点荒谬


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

首先,您不需要手动构建
值,只需使用:

然后,您必须将填写的模板添加到视图的
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>
<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>
现在回到你们的活动。除非您添加了自定义事件,否则不存在
“fname”
事件。但是没有必要这样做,当
fname
被更改时,模型将触发
“change”
“change:fname”
事件;您只需要关心
“更改”
,尽管:

initialize: function() {
    _.bindAll(this, 'render');
    this.model.on("change", this.render);
},
我还使用将
render
绑定到您的视图实例,这样您就不必担心
this.model.on
的第三个参数

现在你有了一些有效的方法:


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

<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>
<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>
演示:


这种方法可能是最常见的,没有什么问题。我认为你误解了前面的答案想要告诉你的内容。模板已经选择了要通过
显示的信息,因此没有理由不在尝试显示前查看是否设置了
fname
。根据数据的性质,您可能希望在模板中使用
if(!(fname).isUndefined())
等,但简单的真实性检查可能就可以了;
age
在某些情况下可能是一个问题,因此您可能希望对其更加严格。

您可以在模板中使用if语句,有条件地显示HTML块。下面是一个关于SO的示例:我之所以不使用toJSON()是因为该模型具有一些“复杂”属性(即其他模型)。我知道生成的JSON只包含嵌套的对象,但我的模板不是“嵌套的”——它们是独立的模板。因此,我实际上不希望JSON中包含“复杂”嵌套属性。@杰克:在这种情况下,我建议在模型中添加一个方法,该方法对JSON进行简化。但你的问题很小。
<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: function() {
    var values   = this.model.toJSON();
    var template = $('#Person-Template').html();
    this.$el.html(_.template(template, values));
    return this;
}