使用JavaScript对象替换字符串值

7

我目前正在为NodeJs制作一个小模块,需要一些帮助。

我这样说吧。我有一个包含字符串的变量。它包含一个HTML值的字符串。现在我需要使用我的对象{"title": "我的标题"}来替换类似$(title)这样的内容。这可以扩展到用户提供的任何内容。这是当前的代码。我认为我需要使用正则表达式来完成这个操作。你们能帮我吗?

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" });


由于您正在使用Node,因此请使用众多能胜任的模板引擎之一,例如ejs。 - user663031
4个回答

11
您可以使用正则表达式来编写一个简单的模板函数。
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

详细信息请点击这里

编辑

如评论中所提到的那样,它实际上可以重构为

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

jsfiddle

希望这能帮到你


当然,但这不能处理像 $(title.toUpperCase()) 这样的内容。 - user663031
1
你可以跳过循环,直接使用 return tpl.replace(/\$\(([^\)]+)?\)/g, function(_, match) { return data[match]; }); - user663031
@torazaburo,OP 没有要求一个复杂的替换器,大多数情况下只需要简单的替换器。因此,我已经重构了替换函数。 - shakib
1
我刚在Chrome的控制台中尝试了一下,它没有替换我的字符串中的任何内容。 - DevonDahon

8
这个解决方案使用 模板字符串 来实现你想要的所有功能。
相比另一个答案中提出的天真的自制基于正则表达式的模板替换策略,这个解决方案具有支持任意计算的优点,例如:
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"

1
有没有办法让替换器在模板字符串引用“obj”中不存在的键时工作? - tettoffensive
"eval" 可能很危险 - Thomas Decaux

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上运行编程示例。请注意保留HTML代码。

我使用NodeJs流来读取HTML文件。我能用它来处理这个吗? - Chathula Sampath Perera
NodeJS 5.0和4.0支持模板字符串(当您使用--harmony启动节点时),但您不能将输入流转换为模板字符串。它们必须由“`”构造。 - Matthisk
我认为你不需要在模板字符串中使用 --harmony 标志。 - user663031

0
var binddingData=function(id,data){
    var me=this,
        arr=[];
    arr=getControlBindding(id);
    arr.forEach(function(node){
        var content=getBinddingContent(node.getAttribute('DataTemp'),data);
        binddingToHtml(node,content);
    })

}
var getControlBindding=function(id){
    var me=this;
    return document.querySelectorAll('[DataTemp]');
}


var getBinddingContent=function(temp,data){
    var me=this,
        res='',
        hasNull=false;
    if(temp==null||typeof temp=='undefined'){
            return res;
        }
    res= temp.replace(/\$\{([^\}]+)?\}/g, function($1, $2) { 
        if(data[$2]==null||typeof data[$2]=='undefined'){
            hasNull=true;
        }
        return data[$2]; 
    });
    return hasNull?'':res;

}

var binddingToHtml=function(node,content){
    var me=this;
    if(node.getAttribute('IsDateTime')){
        node.innerText='';//if u want change it to datetime string
        return;
    }
    if(node.getAttribute('AddBr') && content==''){
        node.innerText='';
        var brTag=document.createElement('br');
        node.appendChild(brTag);
        return;
    }
   node.innerText=content;
}

您可以通过调用“标签”来使用:

<div DataTemp="${d1}"></div> 
    <div DataTemp="${d2}"></div>
    <div DataTemp="${d3}"></div> 
    <div DataTemp="${d3}+ +${d1}"></div> 
    <div DataTemp="${d3}/${d1}"></div>     
    <div DataTemp="${d4}\${d1}"></div>     
    <div DataTemp="(${d5}\${d1})"></div> 
    <div DataTemp="(${d3}\${d1})"></div>

使用数据 var data={d1:'t1',d2:'t2',d3:'t3'}



1
欢迎来到SO。为了使您的答案更有帮助,请先给出描述,然后再发布解决问题的代码。 - SEYED BABAK ASHRAFI

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接