我正在构建一个Web应用程序(使用原型),需要在DOM中添加大量的HTML。其中大多数是包含具有各种属性的元素的行。
目前,我在变量和
中保留了一行空白的HTMLvar 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中的代码,因此插入的新元素是相同的。当我有40行HTML进入blankRow然后我也必须逃避它时,它会变得很糟糕。
有更简单的方法吗?我想到了urlencoding,然后在插入之前解码它,但这仍然意味着一个blankRow和大量的转义。
PHP等人的eof函数是什么意思
$blankRow = <<<EOF
text
text
EOF;
这意味着没有逃脱,但它仍然需要一个blankRow。
在这种情况下你做了什么?
在原型中使用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);
答案 0 :(得分:20)
这是最佳做法吗?
没有。事实上,你有HTML注入问题导致错误,并且在最坏的情况下,注入的字符串可能包含用户提交的内容,XSS安全漏洞。
将纯文本内容和属性值放入HTML字符串时,必须对它们进行HTML编码。在PHP中,您必须在进入HTML的字符串上调用htmlspecialchars()
才能执行此操作。在JavaScript中,你没有内置的HTML转义函数,所以你必须自己创建,例如。通过在进入HTML的字符串上使用s.replace(/&/g, '&').replace(/</g, '<').replace(/"/g, '"')
。
的onclick = “someFunc(\ '{STRING} \');”
这是逃离混乱的全新程度。在事件处理程序属性中的JavaScript字符串文字中,您必须对字符串进行JS编码(\
- 转义'
和\
以及一些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);
});
如果必须从字符串模板创建内容,请确保模板化函数默认情况下HTML转义每次替换,并通过选择已解析内容中的节点来附加事件以调用click(function() { ... })
。或者使用事件委托(例如jQuery live()
)来处理事件,而不必在添加时绑定到新节点。
答案 1 :(得分:5)
你用一种好的方式做到这一点,考虑到其他方式,这是非常快的。
一个替代的,假设干净的解决方案是在javascript中构建您要使用的DOM元素,通过调用几个
使用document.createElement(的tagName);
但是,在我的思想中,你的代码会迅速增长。
另一个,我最喜欢的创建DOM的方法是在HTML主体内放置要复制的代码,给它一个className和/或一个像“template”这样的id,另外(使用css)隐藏它,然后根据事件的需要处理它,方法是返回元素,克隆它,并在追加它所属的位置之前设置你想要的属性
答案 2 :(得分:1)
如果我理解你的话,你的问题是关于用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('');
懒惰的问题:坚持懒惰是非常困难的