Replace string value with javascript object

2020-03-19 03:21发布

I am currently making a small module for NodeJs. For which I need a small help.

I will tell it like this. I have a variable with string. It contains a string html value. Now I need to replace $(title) something like this with my object { "title" : "my title" }. This can be expanded to anything with user provide. This is current code.I think that I need RegEx for do this. Can you guys help me with this?

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

3条回答
爷的心禁止访问
2楼-- · 2020-03-19 03:37

This solution uses template strings to do everything you want.

This solution has the advantage that, in contrast to the naive roll-your-own regexp-based template replacement strategy as proposed in another answer, it supports arbitrary calculations, as in

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

In this version of replacer, we use new Function to create a function which takes the object properties as parameters, and returns the template passed in evaluated as a template string. Then we invoke that function with the values of the object properties.

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

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

We define the template using ${} for substitutions (instead of $()), but escaping as \${ to prevent evaluation. (We could also just specify it as a regular string literal, but would then lose multi-line capability).

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>`;

Now things work exactly as you want:

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

Simple example:

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

Here's an example of calculated fields:

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

or even

> replacer("My name is ${last ? lastName : firstName}", 
    {lastName: "Jones", firstName: "Bob", last: true})
< "My name is Jones"
查看更多
对你真心纯属浪费
3楼-- · 2020-03-19 03:53

Since you are using ES6 template string you can use a feature called 'tagged template strings'. Using tagged template strings you are allowed to modify the output of a template string. You create tagged template string by putting a 'tag' in front of the template string, the 'tag' is a reference to a method that will receive the string parts in a list as the first argument and the interpolation values as remaining arguments. The MDN page on template strings already provides an example template string 'tag' that we can use:

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('');
 });
}

You use the 'tag' by calling:

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>`;

Notice that interpolation of variables uses the syntax ${'key'} instead of $(key). You can now call the produced function to get the desired result:

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

Run the code example on es6console

查看更多
够拽才男人
4楼-- · 2020-03-19 04:02

You can use a simple template function using regex,

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

use like

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

jsfiddle

detail here

EDIT

Actually as torazaburo mentioned in the comment, it can be refactored as

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

jsfiddle

hope this helps

查看更多
登录 后发表回答