动态更改innerHTML设置
Change innerHTML set on the fly
我需要使用innerHTML动态更改每个节点上设置的值。
我找到的最接近的解是:
...
Object.defineProperty(Element.prototype, 'innerHTML', {
set: function () {
// get value (ok)
var value = arguments[0];
// change it (ok)
var new_value = my_function(value);
// set it (problem)
this.innerHTML = new_value; // LOOP
}
}
...
但显然这是一个无限循环。是否有一种方法来调用原来的innerHTML集?
我也试过代理的方式,但我不能使它工作。
更多细节:
我正在做一个实验项目,它使用反向代理来生成和添加CSP策略到一个网站,所以:
- 网站的所有者会意识到这些"覆盖"
- 我需要处理客户端生成的任何js代码,这些代码可能触发政策
- 我需要在内容安全策略引擎评估之前修改它!(这是需要这个"不那么好"解决方案的主要问题)
强制警告:在任何生产级代码中,重写Element.prototype
的任何属性的setter和getter都注定是一个坏主意。如果您使用任何依赖于innerHTML
的库来正常工作,或者项目中的其他开发人员不知道这些更改,那么事情可能会变得奇怪。您也将失去在应用程序的其他部分"正常"使用innerHTML
的能力。
也就是说,由于你没有提供任何关于为什么要这样做的信息,我只是假设你知道这些注意事项,并且你仍然想覆盖浏览器自己的功能,可能是出于开发目的。
解决方案:您为Element.prototype.innerHTML
重写了浏览器的本机setter,但是您还需要原始setter来实现您的目标。这可以使用Object来完成。getOwnPropertyDescriptor,它是Object.defineProperty
的"对应"。
(function() {
//Store the original "hidden" getter and setter functions from Element.prototype
//using Object.getOwnPropertyDescriptor
var originalSet = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML').set;
Object.defineProperty(Element.prototype, 'innerHTML', {
set: function (value) {
// change it (ok)
var new_value = my_function(value);
//Call the original setter
return originalSet.call(this, new_value);
}
});
function my_function(value) {
//Do whatever you want here
return value + ' World!';
}
})();
//Test
document.getElementById('test').innerHTML = 'Hello';
<div id="test"></div>
对于任意HTML字符串,没有直接的方法可以做到这一点,没有
问题是你正在使用一个任意的HTML字符串。目前在元素上设置任意HTML的唯一方法是使用innerHTML
。您必须找到另一种方法在元素上设置任意HTML,例如将HTML附加到临时节点并获取其内容:
// Attempt: build a temporary element, append the HTML to it,
// then grab the contents
var div = document.createElement( 'div' );
div.innerHTML = new_value;
var elements = div.childNodes;
for( var i = 0; i < elements.length; i++ ) {
this.appendChild( elements[ i ] );
}
然而,这遇到了同样的问题,div.innerHTML = new_value;
将永远递归,因为您修改了任意HTML设置的唯一入口点。
我能想到的唯一解决方案是实现一个真正的,完整的HTML解析器,可以采用任意HTML字符串,并将其转换为DOM节点,如document.createElement('p')
等,然后您可以将appendChild
附加到当前元素。然而,这将是一个糟糕的、过度设计的解决方案。
撇开这些不谈,您不应该这样做。这段代码会毁了某人的一天。它违背了我们在前端开发中所遵循的几个原则:
- 不要修改默认的对象原型。任何碰巧运行此代码的人,或者甚至在同一页面上运行代码的人(如第三方跟踪库)都将被从他们下面拉出地毯。追踪出了什么问题几乎是不可能的——没有人会想到去寻找
innerHTML
劫持。 - setter通常用于计算属性或具有副作用的属性。你劫持了一个值并改变了它。你面临一个处理问题——如果有人第二次设置已经被劫持的值,会发生什么?
- 不要写复杂的代码。这个代码无疑是一个"棘手"的解决方案。
最干净的解决方案可能只是在需要的地方使用my_function
。它是可读的、简短的、简单的、普通的编程:
someElement.innerHTML = my_function(value);
您也可以定义一个方法(我将使用method over property,因为它从用户那里获取值),如:
Element.prototype.setUpdatedHTML = function(html) {
this.innerHTML = my_function(html);
}
这样,当开发人员遇到setUpdatedHTML
时,它显然是非标准的,他们可以更容易地去寻找劫持元素原型的人。
- 在CoffeeScript中设置innerHTML
- 使用内部脚本设置innerHTML
- 应该是在设置 innerHTML 之前“清理”的元素
- 未捕获的语法错误:无法在“元素”上设置“innerHTML”属性:提供的标记是无效的 XML
- 设置 innerHTML 不会设置它
- 在 Web 视图中设置 innerHTML 将替换整个文档,而不仅仅是元素
- 如何使用jquery或javascript使用选定的下拉选项文本设置innerhtml
- 移除子节点(或元素)或设置innerHTML=“”&”;
- 设置innerHTML与使用Javascript设置值
- 如何防止jQuery转换 回到 设置innerHTML时
- 未捕获的类型错误:不能设置属性'innerHTML'为hiddenfield设置innerhtml时为n
- 设置 innerHTML:为什么它不会更新 DOM
- IE9的createElement和设置innerHTML上的删除标签的集合操作
- 访问通过设置innerHTML创建的HTML元素
- 设置innerHTML的函数调用不工作-给出未定义
- 为什么设置innerHTML不起作用
- 安全使用AJAX和设置innerHTML
- javascript没有设置innerHTML
- 不能设置innerHTML
- 设置innerHTML字符串会产生语法错误