我想从模板创建一个javascript对象。问题是我事先不知道模板会是什么样子。举个简单的例子,如果我有模板函数
template = function (data) {
return {
title: data.title
}
}
然后我可以运行template({ title: "Steve" })
并取回对象
{ title: "Steve" }
因为在我调用模板函数之前不会评估data.title
。但是我根据用户输入构建一个对象,其中字段名称事先是未知的,并且可以深深嵌套在对象中的任何位置。
如果我定义了事先返回的对象,那么示例中的data.title
字段已经被评估,并且不会使用输入数据。例如,我希望能够像
obj = { title: this.title }
然后将模板重新定义为
template = function () {
return obj
}
并致电template.call({title:"Steve"})
。但目前我回来了
{ title: undefined }
因为我在定义this.title
时已经评估了obj
。也许我以错误的方式接近这个,因为我不断得出结论,我必须通过对其进行字符串化来修改函数,修改字符串以包含未评估的代码this.title
并创建一个字符串中的新函数。但这似乎是一个非常糟糕的主意。
遍历该对象寻找要替换的特殊值似乎既昂贵又复杂。我也找了一些javascript对象模板库,但没找到任何东西。
编辑:为了更清楚地表明输入数据和模板结构不一定匹配,我可能想要一个看起来像
的模板template = function (data) {
return {
name: "Alfred",
stats: {
age: 32,
position: {
level: 10,
title: data.title
}
}
}
}
并致电template({title:"Manager"})
以获取
{ "姓名":" Alfred", " stats":{ "年龄":32, "职位":{ "等级":10, " title":"经理" } } }
答案 0 :(得分:8)
所以我设法通过(ab)使用函数作为元数据来解决这个问题,以标记应该在模板中替换的值。这可以通过两件事来实现:
使用像这样的模板生成器
var templateMaker = function (object) {
return function (context) {
var replacer = function (key, val) {
if (typeof val === 'function') {
return context[val()]
}
return val;
}
return JSON.parse(JSON.stringify(obj, replacer))
}
}
我创建了一个模板对象,用返回字段名称
的函数替换字段名称var obj = {
name: "Alfred",
stats: {
age: 32,
position: {
title: function () { return 'title' },
level: function () { return 'level' }
}
}
}
然后我创建模板函数,定义我的输入,并将其渲染到对象
var template = templateMaker(obj);
var data = {
title: "Manager",
level: 10
}
var rendered = template(data);
神奇地,对象输出看起来像
{
"name": "Alfred",
"stats": {
"age": 32,
"position": {
"title": "Manager",
"level": 10
}
}
}
答案 1 :(得分:4)
也许像Mustache这样的模板引擎可以帮助你解决这个问题。
您可以在字符串中定义对象模板:
var template = '{ title: {{title}} }';
然后用数据渲染它,并将其转换为json:
var data = {title: 'I am title'};
var obj = JSON.parse(Mustache.render(template, data));
<强>更新强>:
我读了你更新的例子,这里是相应的例子:
var template = JSON.stringify({
name: "Alfred",
stats: {
age: 32,
position: {
level: 10,
title: '{{title}}'
}
}
});
var data = {title: 'I am title'};
var obj = JSON.parse(Mustache.render(template, data));
obj.stats.position.title == "I am title";