可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Hey there, I've got a block of HTML that I'm going to be using repeatedly (at various times during a users visit, not at once). I think that the best way to accomplish this is to create an HTML div, hide it, and when needed take its innerHTML and do a replace() on several keywords. As an example HTML block...
<div id='sample'>
<h4>%TITLE%</h4>
<p>Text text %KEYWORD% text</p>
<p>%CONTENT%</p>
<img src="images/%ID%/1.jpg" />
</div>
Would the best way to replace those keywords with dynamic data be to go...
template = document.getElementById('sample');
template = template.replace(/%TITLE%/, some_var_with_title);
template = template.replace(/%KEYWORD%/, some_var_with_keyword);
template = template.replace(/%CONTENT%/, some_var_with_content);
template = template.replace(/%ID%/, some_var_with_id);
It just feels like I've chosen a stupid way to do this. Does anyone have any suggestions on how to do this faster, smarter, or better in any way? This code will be executed fairly often during a users visit, sometimes as often as once every 3-4 seconds.
Thanks in advance.
回答1:
I doubt there will be anything more efficient. The alternative would be splitting it into parts and then concatenating, but I don't think that would be much efficient. Perhaps even less, considering that every concatenation results in a new string which has the same size as its operands.
Added: This is probably the most elegant way to write this. Besides - what are you worried about? Memory usage? It's abundant and Javascript has a decent memory manager. Execution speed? Then you must have some gigantic string. IMHO this is good.
回答2:
It looks like you want to use a template.
//Updated 28 October 2011: Now allows 0, NaN, false, null and undefined in output.
function template( templateid, data ){
return document.getElementById( templateid ).innerHTML
.replace(
/%(\w*)%/g, // or /{(\w*)}/g for "{this} instead of %this%"
function( m, key ){
return data.hasOwnProperty( key ) ? data[ key ] : "";
}
);
}
Explanation of the code:
- Expects
templateid
to be the id of an existing element.
- Expects
data
to be an object with the data.
- Uses two parameters to replace to do the substitution:
- The first is a regexp that searches for all
%keys%
(or {keys}
if you use the alternate version). The key can be a combination of A-Z, a-z, 0-9 and underscore _.
- The second is a anonymous function that gets called for every match.
- The anonymous function searches the data object for the key that the regexp found.
If the key is found in the data, then the value of the key is returned and that value will be replacing the key in the final output. If the key isn't found, an empty string is returned.
Example of template:
<div id="mytemplate">
<p>%test%</p>
<p>%word%</p>
</div>
Example of call:
document.getElementById("my").innerHTML=template("mytemplate",{test:"MYTEST",word:"MYWORD"});
回答3:
You could probably adapt this code to do what you want:
var user = {
"firstName": "John",
"login": "john_doe",
"password": "test",
};
var textbody = ""
+"Hey {firstName},\n"
+"\n"
+"You recently requested your password.\n"
+"login: {login}\n"
+"password: {password}\n"
+"\n"
+"If you did not request your password, please disregard this message.\n"
+"";
textbody = textbody.replace(/{[^{}]+}/g, function(key){
return user[key.replace(/[{}]+/g, "")] || "";
});
You might also want to look into JavaScriptTemplates
回答4:
Template Replacement
A quick and easy solution will be to use the String.prototype.replace method. It takes a second param that can be either a value or a function:
function replaceMe(template, data) {
const pattern = /\{(.*?)\}/g; // {property}
return template.replace(pattern, (match, token) => data[token]);
}
Example:
const html = `
<div>
<h4>{title}</h4>
<p>My name is {name}</p>
<img src="{url}" />
</div>
`;
const data = {
title: 'My Profile',
name: 'John Smith',
url: 'http://images/john.jpeg'
};
And call it like so:
replaceMe(html, data);
回答5:
You can make it more efficient by chaining the replaces instead of making all these interim assignments.
i.e.
with(document.getElementById('sample'))
{
innerHTML = innerHTML.replace(a, A).replace(b, B).replace(c, C); //etc
}
回答6:
If you're willing to use the Prototype library, they have nice built in templating functionality.
That would look like:
element.innerHTML = (new Template(element.innerHTML)).evaluate({
title: 'a title',
keyword: 'some keyword',
content: 'A bunch of content',
id: 'id here'
})
This would be especially nice if you were running your code in a loop due to the ease of creating JSON objects/Javascript object literals.
Still, I wouldn't expect any speed increase.
Also, you would need to change your delimiter style to #{keyword}
rather than %keyword%
回答7:
Your method is a standard way to implement a poor-man's templating system, so it's fine.
It could be worth your while to check out some JavaScript templating libraries, such as JST.
回答8:
This approach generates function templates that can be cached:
function compileMessage (message) {
return new Function('obj', 'with(obj){ return \'' +
message.replace(/\n/g, '\\n').split(/{{([^{}]+)}}/g).map(function (expression, i) {
return i%2 ? ( '\'+(' + expression.trim() + ')+\'' ) : expression;
}).join('') +
'\'; }');
}
var renderMessage = compileMessage('Hi {{ recipient.first_name }},\n\n' +
'Lorem ipsum dolor sit amet...\n\n' +
'Best Regarts,\n\n' +
'{{ sender.first_name }}');
renderMessage({
recipient: {
first_name: 'John'
},
sender: {
first_name: 'William'
}
});
returns:
"Hi John,
Lorem ipsum dolor sit amet...
Best Regarts,
William"
回答9:
Mustachejs is great for really elegant templating:
<div id='sample'>
<h4>{{TITLE}}</h4>
<p>Text text {{KEYWORD}} text</p>
<p>{{CONTENT}}</p>
<img src="images/{{ID}}/1.jpg" />
</div>
You can then use the template something like this:
var template = document.getElementById(templateid).innerHTML;
var newHtml = Mustache.render(template, {
TITLE: some_var_with_title,
KEYWORD: some_var_with_keyword,
CONTENT: some_var_with_content,
ID: some_var_with_id
});
document.getElementById('sample').innerHTML = newHtml;
This especially works nicely if you are getting JSON back from an Ajax call - you can just pass it straight in to the Mustache.render()
call.
Slight variations allow for running the same template on each the browser or the server. See https://github.com/janl/mustache.js for more details.
回答10:
Try this: http://json2html.com/
It supports complex JSON objects as well.
回答11:
var template = "<div id='sample'><h4>%VAR%</h4><p>Text text %VAR% text</p><p>%VAR%</p><img src="images/%VAR%/1.jpg" /></div>";
var replace = function(temp,replace){
temp = temp.split('%VAR%');
for(var i in replace){
if(typeof temp[i] != 'undefined'){
temp[i] = temp[i] + replace[i];
}
}
return temp.join('');
}
replace(template,['title','keyword','content','id'])