当前位置: 首页 > 图文教程 > 网络编程 > Javascript > js innerHTML 的一些问题的解决方法

Javascript
javascript radio list的实现细节(多浏览器兼容)
IE在DOM操作有表单控件时的bug
trim原型函数看js正则表达式的性能
js 禁用浏览器的后退功能的简单方法
IE和Firefox下javascript的兼容写法小结
兼容ie和firefox js关闭代码
用tip解决Ext列宽度不够的问题
firefox getyear() getFullYear数获取年份的问题
javascript iFrame研究
FLASH 广告之外的链接
firefox TBODY 用js显示和隐藏时出现错位的解决方法
Javascript 获取LI里的内容
比较全的JS checkbox全选、取消全选、删除功能代码
JS checkbox控制操作代码
document.all与getElementById、getElementsByName、getElementsByTagName用法区别-document.all
document.all与getElementById、getElementsByName、getElementsByTagName用法区别-getElementById
简单通用的JS滑动门代码
Javascript select控件操作大全(新增、修改、删除、选中、清空、判断存在等)
js 提交和设置表单的值
flash javascript之间的通讯方法小结

Javascript 中的 js innerHTML 的一些问题的解决方法


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-12   浏览: 312 ::
收藏到网摘: n/a

innerHTML 属性的使用非常流行,因为他提供了简单的方法完全替代一个 HTML 元素的内容。另外一个方法是使用 DOM Level 2 API(removeChild, createElement, appendChild)。但很显然,使用 innerHTML 修改 DOM tree 是非常容易且有效的方法。 然而,你需要知道 innerHTML 有一些自身的问题:
1、当 HTML 字符串包含一个标记为 defer 的 script 标签(<script defer>…</script>)时,如 innerHTML 属性处理不当,在 Internet Explorer 上会引起脚本注入攻击。
2、设置 innerHTML 将会破坏现有的已注册了事件处理函数的 HTML 元素,会在某些浏览器上引起内存泄露的潜在危险。
还有几个其他次要的缺点,也值得一提的:
1、你不能得到刚刚创建的元素的引用,需要你手动添加代码才能取得那些引用(使用 DOM APIs)。
2、你不能在所有浏览器的所有 HTML 元素上设置 innerHTML 属性(比如,Internet Explorer 不允许你在表格的行元素上设置innerHTML 属性)。
我更关注与使用 innerHTML 属性相关的安全和内存问题。很显然,这不是新问题,已经有能人围绕这些中的某些问题想出了方法。
Douglas Crockford 写了一个 清除函数 ,该函数负责中止由于 HTML 元素注册事件处理函数引起的一些循环引用,并允许垃圾回收器(garbage collector)释放与这些 HTML 元素关联的内存。
从 HTML 字符串中移除 script 标签并不像看上去那么容易。一个正则表达式可以达到预期效果,虽然很难知道是否覆盖了所有的可能性。这里是我的解决方案:
/<script[^>]*>[\S\s]*?<\/script[^>]*>/ig
现在,让我们将这两种技术结合在到一个单独的 setInnerHTML 函数中,并将 setInnerHTML 函数绑定到 YUI 的 YAHOO.util.Dom 上:
YAHOO.util.Dom.setInnerHTML = function (el, html) {
el = YAHOO.util.Dom.get(el);
if (!el || typeof html !== 'string') {
return null;
}
// 中止循环引用
(function (o) {
var a = o.attributes, i, l, n, c;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
n = a[i].name;
if (typeof o[n] === 'function') {
o[n] = null;
}
}
}
a = o.childNodes;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
c = o.childNodes[i];
// 清除子节点
arguments.callee(c);
// 移除所有通过YUI的addListener注册到元素上所有监听程序
YAHOO.util.Event.purgeElement(c);
}
}
})(el);
// 从HTML字符串中移除script,并设置innerHTML属性
el.innerHTML = html.replace(/<script[^>]*>[\S\s]*?<\/script[^>]*>/ig, "");
// 返回第一个子节点的引用
return el.firstChild;
};
如果此函数还应有其他任何内容或者在正则表达式中遗漏了什么,请让我知道。
很明显,在网页上还有很多其他注入恶意代码的方法。setInnerHTML 函数仅能在所有 A-grade 浏览器上规格化 <script> 标签的执行行为。如果你准备注入不能信任的 HTML 代码,务必首先在服务器端过滤,已有许多库可以做到这点。