我正在构建一个web应用程序(使用prototype),它需要将大量的HTML添加到DOM中。其中大多数是包含具有各种属性的元素的行。
目前,我在一个变量中保留了一个空白的HTML行,
var blankRow = '<tr><td>'
+'<a href="{LINK}" onclick="someFunc(\'{STRING}\');">{WORD}</a>'
+'</td></tr>';
function insertRow(o) {
newRow = blankRow
.sub('{LINK}',o.link)
.sub('{STRING}',o.string)
.sub('{WORD}',o.word);
$('tbodyElem').insert( newRow );
}现在,这一切都运行得很好,但这是最佳实践吗?
当我更新页面上的代码时,我必须更新blankRow中的代码,所以插入的新元素是相同的。当我在一个blankRow中有40行超文本标记语言时,它变得很糟糕,然后我也不得不转义它。
有没有更简单的方法?我在考虑对blankRow进行编码,然后在插入之前对其进行解码,但这仍然意味着but和大量转义。
这意味着什么将是一个类似PHP等人的eof函数。
$blankRow = <<<EOF
text
text
EOF;这将意味着无法转义,但它仍然需要一个blankRow。
在这种情况下你会怎么做?
已解决
最终在prototype中使用了DOMBuilder。不需要其他库:
$w('a div p span img table thead td th tr tbody tfoot input').each(function(e) {
window['$' + e] = function() {
return new Element(e, arguments[0]);
}
});
newPart = $div({id: 'partition-4'})
.insert( $p()
.insert('<b>Stuff</b>')
)
.insert( $p({
id: 'a-p'})
.insert('<b>More stuff</b>')
);
$('parentDiv').insert(newPart);请参阅我的解决方案here或here。
发布于 2010-05-15 20:08:27
这是最佳实践吗?
不是的。事实上,您已经遇到了导致bug的HTML注入问题,在最糟糕的情况下,注入的字符串可能包含用户提交的内容,XSS安全漏洞。
将纯文本内容和属性值放入HTML字符串中时,必须对它们进行HTML编码。在PHP中,你必须在进入超文本标记语言的字符串上调用htmlspecialchars()。在JavaScript中,你没有得到一个内置的超文本标记语言转义函数,所以你必须创建自己的函数,例如。通过对进入超文本标记语言的字符串使用s.replace(/&/g, '&').replace(/</g, '<').replace(/"/g, '"')。
字符串onclick="someFunc(\'{STRING}\');“
这是一个全新的摆脱混乱的水平。在事件处理程序属性内的JavaScript字符串文本中,必须对字符串进行JS编码(\、-escaping、'和\加上几个Unicode字符以保证完整性),然后对结果进行HTML编码。否则,字符串可能会突破其字符串文字分隔符,并注入任意JS代码。在所有情况下都要避免内联事件处理程序属性,尤其是在模板中。
用HTML字符串创建页面内容很糟糕。您很可能会出现转义错误,并危及应用程序的安全性。使用类似于DOM的方法,您不必担心这一点。您似乎正在使用jQuery,因此尝试使用jQuery 1.4元素创建快捷方式:
$('<tr>').append(
$('<td>').append(
$('<a>', {
href: o.link,
text: o.word,
onclick: function() {
someFunc(o.string);
}
})
)
);或者,将空白行作为HTML语言保留在文档中,然后将其隐藏(display: none)或在开始时将其从文档中分离(removeChild或jQuery detach)。然后,当您需要新行时,克隆空白行并进行所需的更改:
var blankRow= $('#blankRow').detach();
...
var newRow= blankRow.clone();
var link= newRow.find('td>a');
link.attr('href': o.link);
link.text(o.word);
link.click(function() {
someFunc(o.string);
});如果您必须从字符串模板创建内容,请确保您的模板函数在默认情况下会转义所有替换内容,并通过选择解析内容内的节点来附加事件以调用click(function() { ... })。或使用事件委派(例如,jQuery live())来处理事件,而不必在添加时绑定到新节点。
发布于 2010-05-15 19:20:45
你使用了一种好的方法,考虑到其他方式,这是相当快的。
另一种假定干净的替代解决方案是在javascript中构建要使用的DOM元素,方法是调用几个
document.createElement(tagName);
但在我看来,您的代码将会迅速增长,而且毫无意义。
另一种方法,也是我最喜欢的实现DOM创建的方法,就是将想要复制的代码放在HTML体中,给它一个className和/或一个类似于"template“的id (使用css )来另外隐藏它,然后在事件发生时根据需要处理它,方法是取回元素,克隆它,并设置您想要的属性,然后添加到它所属的位置
发布于 2010-05-15 19:21:18
如果我理解得很好,您的问题是关于初始化大型字符串的方式,就像在PHP (或Perl )中那样?对于我使用的长(多行)字符串:
var blankRow = [
'a line',
'another line',
'still more lines',
'lines lines lines',
'... etc'
].join('')你也可以使用反斜杠来继续,但这可能会变得有点混乱:
var blankRow = 'a line\
another line\
still more lines\
lines lines lines\
... etc';基于评论进行编辑:我也很懒!所以我用这个来进行转义:
function qs(str){
str = str || this || '';
return "'"+str+"'";
}
function qd(str){
str = str || this || '';
return '"'+str+'"';
}
String.prototype.qs = qs;
String.prototype.qd = qd;
// applied:
var blankRow = [
'a line',
'another '+qd('line'),
'still more lines',
'lines '+'lines'.qs()+ ' lines',
'... etc'
].join('');懒惰的问题:坚持一个人的懒惰是相当困难的工作
https://stackoverflow.com/questions/2839844
复制相似问题