19

还在学习骨干,请多多包涵;

我正在尝试将带有空白字段的新模型添加到视图中,但是我创建的模板有一大堆

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

获取数据时工作得非常好,它填充它并且一切顺利。当我想创建一个新的(空白)渲染视图时,问题就出现了,它给了我

Uncaught ReferenceError: some_value is not defined

我可以设置defaults(我已经为一些在数据库中具有默认值的设置),但这意味着用空格输入超过 40 个;有没有更好的方法来处理这个?

我正在摆弄下划线模板本身,尝试类似的东西,<%= if(some_value != undefined){ some_value } %>但这似乎也有点麻烦。

4

8 回答 8

25

在包装器对象中传递模板数据。缺少属性访问不会引发错误:

所以,而不是:

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"
于 2013-03-07T23:23:49.997 回答
13

实际上,您可以arguments在模板内部使用:

<% if(!_.isUndefined(arguments[0].foo)) { %>
       ...
<% } %>
于 2014-05-22T13:50:40.013 回答
10

不,

由于下划线模板的实现方式,对此没有实际的修复。

请参阅有关它的讨论

恐怕这只是 with(){} 在 JS 中的工作方式。如果未声明变量,则为 ReferenceError。在保留模板行为的其余部分的同时,我们无能为力。

您可以完成您正在寻找的唯一方法是将对象与另一个对象(如建议的其他答案)包装在一起,或者设置默认值。

于 2013-03-07T23:26:17.957 回答
5

如果您检查生成的模板函数的源代码,您将看到如下内容:

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

这里发生了什么:起初 JS 试图在“obj”中找到你的属性,它是模型(更多关于with语句)。在“obj”范围内找不到该属性,因此 JS 向上遍历直到全局范围并最终抛出异常。

因此,您可以直接指定您的范围来解决此问题:

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

至少它对我有用。

于 2015-07-07T16:35:17.563 回答
3

实际上,您可以访问变量,如初始对象属性。

如果您将调试器激活到模板中,您可以找到包含所有数据的变量“obj”。

所以<%= title %>你应该写而不是<%= obj.title %>

于 2016-03-23T00:33:17.720 回答
0

lodash,一个下划线的替代品,提供了一个带有内置解决方案的模板函数。它可以选择将数据包装在另一个对象中,以避免导致错误的“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;
// }
于 2015-07-28T07:14:48.703 回答
0

一个非常简单的解决方案:您可以确保您的数据集合是规范化的,即所有属性都存在于每个对象中(如果它们未使用,则为空值)。像这样的功能可以帮助:

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 
于 2016-02-18T15:13:21.127 回答
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
<% } %>

正如他的回答中的评论所暗示的那样,这更具可扩展性。

于 2016-02-23T21:32:13.653 回答