2013-03-07 132 views
17

靜止的學習骨幹讓我忍受;忽略下劃線模板中的未定義數據/變量

我想添加空白字段到視圖的新模式,但我已經創建的模板有一大堆

<input value="<%= some_value %>" type="whatever" /> 

作品獲取數據時完全正常,它填充它,一切順利。麻煩出現時,我想創建一個新的(空白)渲染視圖,它給了我

Uncaught ReferenceError: some_value is not defined 

我可以設置defaults(我幾有在DB的默認值做的話),但是這意味着打字其中40人以上有空白;有沒有更好的方式來處理這個問題?

我擺弄下劃線模板本身,嘗試像<%= if(some_value != undefined){ some_value } %>類似的東西,但這似乎也有點麻煩。

回答

8

沒有,

沒有實際修復這是由於下劃線模板的實現方式。

this discussion一下:

I'm afraid that this is simply the way that with(){} works in JS. If the variable isn't declared, it's a ReferenceError. There's nothing we can do about it, while preserving the rest of template behavior.

的唯一方法就可以完成你要尋找的是自動換行對象與另一個對象像其他答案建議,或者設置的默認值。

23

將模板數據傳遞給包裝器對象。缺少屬性訪問將不會引發錯誤:

因此,而不是:

var template = _.template('<%= foo %><%= bar %>'); 
var model = {foo:'foo'}; 
var result = template(model); //-> Error 

嘗試:

var template = _.template('<%= model.foo %><%= model.bar %>'); 
var model = {foo:'foo'}; 
var result = template({model:model}); //-> "foo" 
+2

如果您嘗試訪問model.foo.bar和酒吧不存在 – regretoverflow 2013-10-01 04:59:28

+0

很好的知道,屬性訪​​問將不會引發錯誤仍然失敗。這正是我正在尋找的。我有一個對象,它可能包含一些數據。如果它不在那裏,我只是希望它被忽略。 – Andrei 2015-02-10 14:13:51

10

其實,你可以使用arguments模板內:

<% if(!_.isUndefined(arguments[0].foo)) { %> 
     ... 
<% } %> 
+6

是啊,祝你好運把它放在百萬位 – vsync 2015-09-08 21:47:39

+0

這對我有效。 – 2016-02-23 21:21:52

4

如果您檢查生成的模板功能的源代碼,你會看到這樣的事情:

with (obj||{}) { 
    ... 
    // model property is used as variable name 
    ... 
} 

這裏會發生什麼:首先,JS試圖在「obj」中找到你的財產,這是模型(更多關於with聲明)。這個屬性在「obj」範圍中找不到,所以JS遍歷並遍歷全局範圍,最後拋出異常。

所以,你可以直接指定範圍,以解決這個問題:

<input value="<%= obj.some_value %>" type="whatever" /> 

至少它爲我工作。

+1

這個答案和@德米特里的答案是實際的解決方案 – galki 2015-10-15 02:00:52

0

lodash,一個下劃線替換,提供了一個template函數與一個內置的解決方案。它可以選擇將數據包裝在另一個對象中,以避免導致錯誤的「with」語句。從API文檔

使用範例:

// using the `variable` option to ensure a with-statement isn’t used in the compiled template 
var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' }); 
compiled.source; 
// → function(data) { 
// var __t, __p = ''; 
// __p += 'hi ' + ((__t = (data.user)) == null ? '' : __t) + '!'; 
// return __p; 
// } 
0

一個非常簡單的解決辦法:你可以確保您的數據收集標準化,即所有屬性都存在於每個對象(null值,如果他們沒用過)。這樣的功能可以幫助:

function normalizeCollection (collection, properties) { 
    properties = properties || []; 
    return _.map(collection, function (obj) { 
    return _.assign({}, _.zipObject(properties, _.fill(Array(properties.length), null)), obj); 
    }); 
} 

(注:_.zipObject_.fill可在最新版本的lodash但不強調)

使用方法如下:

var coll = [ 
    { id: 1, name: "Eisenstein"}, 
    { id: 2 } 
]; 

var c = normalizeCollection(coll, ["id", "name", "age"]); 
// Output => 
// [ 
// { age: null, id: 1, name: "Eisenstein" }, 
// { age: null, id: 2, name: null } 
// ] 

當然,您不必永久轉換數據–只需調用模板渲染函數即可調用該函數:

var compiled = _.template(""); // Your template string here 
// var output = compiled(data); // Instead of this 
var output = compiled(normalizeCollection(data)); // Do this 
0

您可以通過向模型添加一個函數並在模板中使用它來進一步抽象@Dmitri的答案。

例如:

型號:

new Model = Backbone.Model.extend({ 
    defaults: { 
     has_prop: function(prop) { 
      return _.isUndefined(this[property]) ? false : true; 
     } 
    } 
}); 

模板:

<% if(has_prop('property')) { %> 
    // Property is available 
<% } %> 

正如他在回答意見認爲這是更加擴展。

2

實際上,您可以訪問初始對象屬性等變量。

如果您將調試器激活到模板中,您可以找到包含所有數據的變量「obj」。

所以不是<%= title %>你應該寫<%= obj.title %>