2012-06-30 56 views
1

我有幾個不同的問題正在進行,我希望這個例子很容易遵循。該代碼使用HTML模板,默認情況下隱藏元素(使用CSS)。 Backbone View使用模型中的數據顯示適當的值,或者如果模式中沒有值,則隱藏UI元素。Backbone.js - 視圖和模型之間的關係?

鑑於這裏的一切在默認情況下(使用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(); 
    } 

}

最後一個問題:它似乎哈克呼召呈現每個updateXYZ()()方法只是確定是否隱藏或顯示的UI元素進行設置。我的模型中有很多屬性,代碼看起來真的很荒謬。

I have been told on SO該視圖不應該負責確定應該或應該顯示什麼。我的問題是,那麼什麼是負責任的?用戶可以執行一些清除名字的(有效)聲調,在這種情況下,我不希望我的視圖顯示「名字:」,後面沒有值。

+0

您可以在模板中使用if語句來有條件地顯示HTML塊。 下面是關於SO的一個例子: http://stackoverflow.com/questions/7230470/how-to-use-if-statements-in-underscore-js-templates – Chris

回答

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> 
現在回到你的活動

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

你不爲三個部分在render獨立的功能,你可以通過它們只是循環。除非你添加了一個自定義的事件,否則不會有這樣的事件。但沒有必要,fname更改時,模型將觸發"change""change: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可能會成爲問題,儘管如此,您可能希望對此稍加嚴格。

+0

我不使用toJSON()的原因是因爲該模型具有一些「複雜」屬性(即其他模型)。我知道生成的JSON只包含嵌套的objets,但我的模板不是'嵌套的' - 它們是單獨的模板。因此,我實際上不需要JSON中包含的「複雜」嵌套屬性。 – Jack

+0

@Jack:在這種情況下,我建議在你的模型中添加一個方法來簡化'toJSON'。但是你的問題的那部分是相當小的。 –