2016-01-11 120 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"