从模板创建 Javascript 对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23194291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create Javascript objects from a template
提问by Drew Greene
I want to create a javascript object from a template. The problem is I don't know what the template is going to look like beforehand. As a simple example, if I had the template function
我想从模板创建一个 javascript 对象。问题是我事先不知道模板会是什么样子。举个简单的例子,如果我有模板函数
template = function (data) {
return {
title: data.title
}
}
then I could run template({ title: "Steve" })
and get back the object
然后我可以运行template({ title: "Steve" })
并取回对象
{ title: "Steve" }
Because data.title
is not evaluated until I call the template function. But I'm constructing an object based on user input where the field names are not known beforehand and could be deeply nested anywhere in the object.
因为data.title
在我调用模板函数之前不会被评估。但是我正在根据用户输入构建一个对象,其中字段名称事先未知,并且可以深入嵌套在对象的任何位置。
If I define the object that is returned beforehand then the data.title
field in the example would already be evaluated and wouldn't use the input data. For example, I want to be able to define the template object like
如果我定义了预先返回的对象,那么data.title
示例中的字段将已经被评估并且不会使用输入数据。例如,我希望能够像这样定义模板对象
obj = { title: this.title }
then redefine the template as
然后将模板重新定义为
template = function () {
return obj
}
and call template.call({title:"Steve"})
. But currently I get back
并调用template.call({title:"Steve"})
。但目前我回来了
{ title: undefined }
because this.title
was already evaluated when I defined obj
. Maybe I'm approaching this the wrong way, because I keep coming to the conclusion that I'd have to modify the function by stringifying it, modifying the string to include the unevaluated code this.title
and creating a new function from the string. But that seems like a plain awful idea.
因为this.title
在我定义obj
. 也许我以错误的方式处理这个问题,因为我不断得出结论,我必须通过字符串化来修改函数,修改字符串以包含未评估的代码this.title
并从字符串创建一个新函数。但这似乎是一个非常糟糕的主意。
And traversing the object looking for special values to replace seems expensive and complicated. I also looked for some sort of javascript object templating library but didn't find anything.
遍历对象寻找特殊值来替换似乎既昂贵又复杂。我还寻找了某种 javascript 对象模板库,但没有找到任何东西。
EDIT:To make it more clear that the input data and the template structure won't necessarily match, I may want have a template that looks like
编辑:为了更清楚地说明输入数据和模板结构不一定匹配,我可能想要一个看起来像的模板
template = function (data) {
return {
name: "Alfred",
stats: {
age: 32,
position: {
level: 10,
title: data.title
}
}
}
}
and call template({title:"Manager"})
to get
并打电话template({title:"Manager"})
给
{ "name": "Alfred", "stats": { "age": 32, "position": { "level": 10, "title": "Manager" } } }
{ "name": "Alfred", "stats": { "age": 32, "position": { "level": 10, "title": "Manager" } } }
回答by Drew Greene
So I've managed to solve this by (ab)using functions as metadata to mark the values that should be replaced in the template. This is made possible by two things:
所以我设法通过(ab)使用函数作为元数据来标记模板中应该替换的值来解决这个问题。这是通过两件事实现的:
- I only need valid JSON values, so I can safely say that functions aren't literal user input
- JSON.stringify has a replacer parameterwhich will traverse the object and can be used to pass the input data to the template
- 我只需要有效的 JSON 值,所以我可以有把握地说函数不是文字用户输入
- JSON.stringify 有一个replacer 参数,它将遍历对象,可用于将输入数据传递给模板
Using a template generator like this
使用这样的模板生成器
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))
}
}
I create a template object, replacing field names with functions that return the field name
我创建了一个模板对象,用返回字段名称的函数替换字段名称
var obj = {
name: "Alfred",
stats: {
age: 32,
position: {
title: function () { return 'title' },
level: function () { return 'level' }
}
}
}
then I create the template function, define my input, and render it to an object
然后我创建模板函数,定义我的输入,并将它呈现给一个对象
var template = templateMaker(obj);
var data = {
title: "Manager",
level: 10
}
var rendered = template(data);
and magically, the object output looks like
神奇的是,对象输出看起来像
{
"name": "Alfred",
"stats": {
"age": 32,
"position": {
"title": "Manager",
"level": 10
}
}
}
{
"name": "Alfred",
"stats": {
"age": 32,
"position": {
"title": "Manager",
"level": 10
}
}
}
回答by wong2
Maybe template engines like Mustachewould help you with this.
也许像Mustache这样的模板引擎会帮助你解决这个问题。
You can define your object template in string:
您可以在字符串中定义对象模板:
var template = '{ title: {{title}} }';
var template = '{ title: {{title}} }';
then render it with the data, and convert it to json:
然后用数据渲染它,并将其转换为json:
var data = {title: 'I am title'};
var obj = JSON.parse(Mustache.render(template, data));
UPDATE:
更新:
I read your updated example, here is the corresponding example:
我阅读了您更新的示例,这是相应的示例:
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";