2016-01-11 86 views
2

我目前正在为NodeJ制作一个小模块。为此我需要一点帮助。用javascript对象替换字符串值

我会这样讲。 我有一个字符串变量。它包含一个字符串html值。现在我需要用我的对象{ "title" : "my title" }替换$(title)这样的东西。这可以扩展到用户提供的任何东西。这是目前的代码。我认为我需要RegEx来做到这一点。你们能帮助我吗?

var html = `<!DOCTYPE html> 
 
<html lang="en"> 
 
<head> 
 
    <meta charset="UTF-8"> 
 
    <title>Document $(title)</title> 
 
</head> 
 
<body> 
 

 
    <h1>Test file, $(text)</h1> 
 

 
</body> 
 
</html>`; 
 

 
function replacer(html, replace) { 
 
    // i need a regex to replace these data 
 
    //return replacedData; 
 
} 
 

 
replacer(html, { "title" : "my title", "text" : "text is this" });

+0

由于您使用的节点上,使用多有能力的模板引擎之一在那里,如EJS。 –

回答

2

您可以使用正则表达式使用一个简单的模板函数的代码示例,

var replacer = function(tpl, data) { 
    var re = /\$\(([^\)]+)?\)/g, match; 
    while(match = re.exec(tpl)) { 
    tpl = tpl.replace(match[0], data[match[1]]) 
    re.lastIndex = 0; 
    } 
    return tpl; 
} 

使用像

var result = replacer(html, { "title" : "my title", "text" : "text is this" }); 

jsfiddle

detail here

编辑

其实在评论中提到torazaburo,可以重构为

var replacer = function(tpl, data) { 
    return tpl.replace(/\$\(([^\)]+)?\)/g, function($1, $2) { return data[$2]; }); 
} 

jsfiddle

希望这有助于

+0

谢谢soo。这一个工作得很好:D –

+0

欢迎:) – shakib

+0

嗯,当然,但这不会用''(title.toUpperCase())''的东西。 –

1

由于您使用ES6模板字符串你可以使用一个功能叫做'tagged template strings'。使用带标签的模板字符串,您可以修改模板字符串的输出。您可以通过在模板字符串前面添加一个'标签'来创建带标签的模板字符串,'标签'是一个方法的引用,该方法将接收列表中的字符串部分作为第一个参数,并将插值作为其余参数接收。模板字符串的MDN页面已经提供了一个示例模板字符串“标签”,我们可以使用:

function template(strings, ...keys) { 
    return (function(...values) { 
    var dict = values[values.length - 1] || {}; 
    var result = [strings[0]]; 
    keys.forEach(function(key, i) { 
     var value = Number.isInteger(key) ? values[key] : dict[key]; 
     result.push(value, strings[i + 1]); 
    }); 
    return result.join(''); 
}); 
} 

通过调用使用“标签”:

var tagged = template`<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Document ${'title'}</title> 
</head> 
<body> 

    <h1>Test file, ${'text'}</h1> 

</body> 
</html>`; 

通知变量插值使用语法${'key'}而不是$(key)。现在,您可以调用生产函数来获得期望的结果:

tagged({ "title" : "my title", "text" : "text is this" }); 

上运行es6console

+0

我使用NodeJs Streams来读取html文件。我可以使用它吗? –

+0

NodeJS 5.0和4.0支持模板字符串(当您使用--harmony启动节点时),但不能将输入流转换为模板字符串。它们必须由'ticks – Matthisk

+0

构建好吧,我会尝试一下:D –

1

此解决方案使用template strings来完成您想要的任何操作。

该解决方案是,在对比的是天真的卷制自己的基于正则表达式模板替换为另一个答案提出的策略,它支持任意计算,如

replacer("My name is ${name.toUpperCase()}", {name: "Bob"}); 

在这个版本的优点replacer,我们使用new Function创建一个函数,该函数将对象属性作为参数,并将传入的模板作为模板字符串返回。然后我们用对象属性的值调用该函数。

function replacer(template, obj) { 
    var keys = Object.keys(obj); 
    var func = Function(...keys, "return `" + template + "`;"); 

    return func(...keys.map(k => obj[k])); 
} 

我们定义为替代(而不是$())使用${}模板,但\${转义来避免评价。 (我们也可以将其指定为常规字符串文字,但会失去多行功能)。

var html = `<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Document \${title}</title> <!-- escape $ --> 
</head> 
<body> 

    <h1>Test file, \${text}</h1>  <!-- escape $ --> 

</body> 
</html>`; 

现在工作的事情完全一样,你想:

replacer(html, { "title" : "my title", "text" : "text is this" }); 

简单的例子:

> replacer("My name is ${name}", {name: "Bob"}) 
< "My name is Bob" 

下面是计算领域的一个例子:

> replacer("My name is ${name.toUpperCase()}", {name: "Bob"}) 
< "My name is BOB" 

甚至

> replacer("My name is ${last ? lastName : firstName}", 
    {lastName: "Jones", firstName: "Bob", last: true}) 
< "My name is Jones"