使用 Javascript 将大块 HTML 插入元素的最佳实践?
Posted
技术标签:
【中文标题】使用 Javascript 将大块 HTML 插入元素的最佳实践?【英文标题】:Best practice for inserting large chunks of HTML into elements with Javascript? 【发布时间】:2011-02-19 20:33:32 【问题描述】:我正在构建一个需要在 DOM 中添加大量 html 的 Web 应用程序(使用原型)。其中大部分是包含具有各种属性的元素的行。
目前我在一个变量中保留了一行空白的 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中的代码,因此插入的新元素是相同的。当我有 40 行 HTML 进入一个 blankRow 时,它会变得很糟糕,然后我也必须转义它。
有没有更简单的方法?我正在考虑 urlencoding,然后在插入之前对其进行解码,但这仍然意味着空白行和大量转义。
什么意思是 eof 函数 a la php et al.
$blankRow = <<<EOF
text
text
EOF;
这意味着没有转义,但它仍然需要一个空白行。
遇到这种情况你会怎么做?
已解决
最终在原型中使用了 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。
【问题讨论】:
你的点击函数总是字符串吗?如果它是一个实际的函数会更好,但不确定这是否是一个选项,你也在使用 jQuery 吗?从你的语法中我不能 100% 确定,但看起来你是。 不建议将许多节点一个接一个地插入 DOM。你应该一次完成。尝试先将它们插入容器对象,然后再从对象插入 DOM。 不,点击功能只是一个例子,主要是它的数字减少了我需要做的转义量。是的,它是原型,应该采用 jquery 的方式,但现在为时已晚。 嘿 vsync 我会先创建容器对象,比如 container = document.createElement('tbody') 把所有的 tr 扔进去然后做一个 $('actualTable').insert(container.childElements( ))?或 .insert( container.innerHTML ) - [iirc insert 想要一个字符串 arg...] 【参考方案1】:你用一种很好的方式来做这件事,考虑到其他方式,这很快。
另一种可能是干净的解决方案是在 javascript 中构建您要使用的 DOM 元素,方法是调用几个
document.createElement(tagName);
但在我看来,你的代码会迅速增长,但不会白费。
另一种,我最喜欢的实现 DOM 创建的方法,是将要复制的代码放在 HTML 正文中,给它一个 className 和/或像“模板”这样的 id,这将另外(使用 css)隐藏它,然后根据需要在事件上处理它,方法是取回元素,克隆它,并在附加它所属的位置之前设置你想要的属性
【讨论】:
【参考方案2】:如果我理解你的话,你的问题是关于初始化大字符串的方式,你将在 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('');
懒惰的问题:坚持一个人的懒惰是相当困难的工作
【讨论】:
啊,这是一个聪明的方法。我提到 PHP 示例的原因是您不需要在中间转义任何内容;) 【参考方案3】:这是最佳做法吗?
没有。实际上,您遇到了导致错误的 HTML 注入问题,并且在最坏的情况下,注入的字符串可能包含用户提交的内容,XSS 安全漏洞。
当您将纯文本内容和属性值放入 HTML 字符串时,您必须对它们进行 HTML 编码。在 PHP 中,您必须在进入 HTML 的字符串上调用 htmlspecialchars()
来执行此操作。在 JavaScript 中,您没有内置的 HTML 转义功能,因此您必须自己制作,例如。通过在进入 HTML 的字符串上使用 s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;')
。
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);
);
如果您必须从字符串模板创建内容,请确保您的模板函数默认对每个替换进行 HTML 转义,并通过选择解析内容中的节点来附加事件以调用 click(function() ... )
。或者使用事件委托(例如 jQuery live()
)来处理事件,而无需在添加时绑定到新节点。
【讨论】:
伙计……多么伟大的使命。谢谢你的帮助。真希望我现在使用 jquery 而不是原型 :( @hamstar:哎呀!我应该发现这是一个原型 ID 选择器$
而不是 jQuery。哦。 Prototype 有一个类似的(IMO:在某些方面更好)创建元素的快捷方式,new Element
。见prototypejs.org/2007/5/12/dom-builder
甜蜜!我可能不得不试一试 :) 干杯
最终以这种方式完成,效果非常好!花了一段时间才弄清楚。如果有人想查看代码,请参阅 gist.github.com/402668 或 pastebin.com/Du5Ejjjj 非常感谢您提供的信息 bobince!
我强烈避免从字符串设置事件处理程序属性。我不记得 Prototype 是否可以解决通常会阻止此工作的许多 IE 错误,但无论如何这都是非常糟糕的做法;像您稍后在代码中所做的那样调用.observe
通常会好得多。 <a href="javascript:void(0)">
也是一种不愉快。考虑一个可点击的跨度或一个按钮(如果你想要的话,它的样式看起来不像一个按钮)。有关此问题的讨论,请参见 ***.com/questions/1291942/…。以上是关于使用 Javascript 将大块 HTML 插入元素的最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 javascript/jquery 将大型 html 块附加到刀片文件?
尝试使用Javascript将HTML元素插入另一个HTML元素