忽略下划线模板中未定义的数据/变量
Ignoring undefined data / vars in an underscore template
仍在学习骨干,请耐心等待;
我试图添加一个新的模型与空白字段的视图,但我已经创建的模板有一大堆
<input value="<%= some_value %>" type="whatever" />
在获取数据时工作得很好,它填充数据,一切都很顺利。当我想创建一个新的(空白)渲染视图时,问题出现了,它给了我
Uncaught ReferenceError: some_value is not defined
我可以设置defaults
(我已经为一些在db中具有默认值的人做了),但这意味着键入超过40个空格;有更好的处理方式吗?
我正在摆弄下划线模板本身,尝试像<%= if(some_value != undefined){ some_value } %>
这样的东西,但这似乎也有点麻烦。
在包装器对象中传递模板数据。缺少属性访问不会抛出错误:
所以,而不是:
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"
实际上,您可以在模板中使用arguments
:
<% if(!_.isUndefined(arguments[0].foo)) { %>
...
<% } %>
不
由于下划线模板的实现方式,没有实际的修复。
请看下面的讨论:
恐怕这就是JS中with(){}的工作方式。如果没有声明变量,它就是一个ReferenceError。在保留模板其他行为的同时,我们对此无能为力。
你可以完成你所寻找的唯一方法是用另一个对象包装对象,就像其他答案建议的那样,或者设置默认值。
如果检查生成的模板函数的源代码,您将看到如下内容:
with (obj||{}) {
...
// model property is used as variable name
...
}
这里发生了什么:首先JS试图在"obj"中找到你的属性,这是模型(更多关于with语句)。这个属性在"obj"作用域中找不到,所以JS向上遍历直到全局作用域,最后抛出异常。
所以,你可以直接指定你的作用域来解决这个问题:<input value="<%= obj.some_value %>" type="whatever" />
实际上,您可以像初始对象属性一样访问变量。
如果你将调试器激活到模板中,你可以找到变量"obj",它包含了你所有的数据。
所以你应该写<%= obj.title %>
<%= title %>
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;
// }
一个非常简单的解决方案:您可以确保您的数据收集是规范化的,即所有属性都存在于每个对象中(如果它们未使用则为空值)。下面的函数可以提供帮助:
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
您可以通过在模型中添加一个函数并在模板中使用它来进一步抽象@Dmitri的答案。
例如:模型:
new Model = Backbone.Model.extend({
defaults: {
has_prop: function(prop) {
return _.isUndefined(this[property]) ? false : true;
}
}
});
模板:
<% if(has_prop('property')) { %>
// Property is available
<% } %>
正如他回答中的评论所暗示的那样,这是更可扩展的
- 当JSON数据=变量时,需要执行循环
- 如何将数据/变量从file_controller.rb传递到application.js
- 当移动到“外部”版本时,“内部”成功 AJAX 中的“数据”变量应该更改为什么
- 从 ajax jQuery 中的数据变量中获取属性
- 将脚本属性(数据变量)传递到 head.js
- 2 个数据变量的 mrender 不起作用
- 如何在 ng-repeat 过滤器中传递 HoDjango views.py 上下文数据变量
- 以简单的方式将多个数据变量传递给 AJAX 函数
- 如何从每个带有类的元素中获取数据变量
- 根据数据变量的d3网络图的颜色链接
- 如何在不同的网站之间共享数据变量或本地存储?iframe?postMessage
- 将数据变量从PHP传递到jquery ui对话框
- 数据变量没有从Vue.js中的监视器上的计算属性更新
- 弹出窗口数据变量传递
- 如何使用jquery发布输入数据变量
- vue .js:如何在.vue模板文件中的vue方法中设置数据变量
- JSON jQuery数据变量
- 从onclick()提取数据变量
- 忽略下划线模板中未定义的数据/变量
- 如何使用php数据变量创建条形图