遍历 DOM 注意点
栏目: JavaScript · 发布时间: 7年前
内容简介:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangxin09/article/details/86693618
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangxin09/article/details/86693618
在实现一个清理 HTML 冗余标签(word 粘贴过来的)功能,最简单的,莫过于:
// MSWordHtmlCleaners.js https://gist.github.com/ronanguilloux/2915995
cleanPaste : function(html) {
// Remove additional MS Word content
html = html.replace(/<(\/)*(\\?xml:|meta|link|span|font|del|ins|st1:|[ovwxp]:)((.|\s)*?)>/gi, ''); // Unwanted
// tags
html = html.replace(/(class|style|type|start)=("(.*?)"|(\w*))/gi, ''); // Unwanted
// sttributes
html = html.replace(/<style(.*?)style>/gi, ''); // Style tags
html = html.replace(/<script(.*?)script>/gi, ''); // Script tags
html = html.replace(/<!--(.*?)-->/gi, ''); // HTML comments
return html;
},
因为某些正则功能的缺失,网页的 JS 正则是不能完全匹配对应标签的。故所以这种通过正则过滤的办法是有潜在问题的。于是考虑另外一种方法,如老外写的这个 http://booden.net/ContentCleaner.aspx,它是通过 DOM 方法删除标签的,——我觉得可行,就拿来改造。遇到的问题不少,记录如下。
首先,他依赖 jQuery,我希望是原生的,开始我以为修改下问题不大,但后来发现没那么容易,首当其冲的是 DOM 遍历。写一个遍历并递归 DOM 的代码不困难,麻烦在于,当你使用 for 遍历,集合的总数是固定的(length),而当你删除了一个元素,等于破坏了这个数组,数组下标也乱了。于是改为 while(firstChild) 循环的方法,有点链表那样的写法,总是会出现死循环的现象,可能是指针有误。
苦于没有办法快放弃的情况下,忽然想起老外那个代码有段函数 removeComments(),想想那正是原生的遍历方法,它是删除注释节点后而继续迭代的。于是拿来改造用,并得到成功!
后来想想,可能这就是迭代器与 for 的区别,因为集合里面的元素允许动态变化,用 for 遍历肯定有问题,这时就适宜用迭代器,诸如 hasNext()、getNextItem() 的 API,尽管会啰嗦点。
在删除 DOM 元素属性时,也遇到这种问题。例如下面代码,每次只能删除一个属性,而不是全部!
var attrs = el.attributes;
for (var i = 0; i < attrs.length; i++) {
console.log(attrs[i]);
el.removeAttribute(attrs[i].name);
}
解决方法是如 MDN 所说的,
for(var i = attrs.length - 1; i >= 0; i--) {
var name = attrs[i].name;
if (attributesAllowed[tag] == null || attributesAllowed[tag].indexOf("|" + name.toLowerCase() + "|") == -1){
node.removeAttribute(name);
}
}
最后,完整的清理 HTML 代码如下
// 清理冗余 HTML
cleanHTML(){
// 类似于 白名单
var tagsAllowed = "|h1|h2|h3|p|div|a|b|strong|br|ol|ul|li|pre|img|br|hr|font|";
var attributesAllowed = {};
attributesAllowed["div"] = "|id|class|";
attributesAllowed["a"] = "|id|class|href|name|";
attributesAllowed["img"] = "|src|";
this.everyNode(this.iframeBody, node => {
var isDelete = false;
if (node.nodeType === 1) {
var tag = node.tagName.toLowerCase();
if (tagsAllowed.indexOf("|" + tag + "|") === -1)
isDelete = true;
if (!isDelete) { // 删除属性
var attrs = node.attributes;
for(var i = attrs.length - 1; i >= 0; i--) {
var name = attrs[i].name;
if (attributesAllowed[tag] == null || attributesAllowed[tag].indexOf("|" + name.toLowerCase() + "|") == -1){
node.removeAttribute(name);
}
}
}
} else if (node.nodeType === 8) {// 删除注释
isDelete = true;
}
return isDelete;
});
},
everyNode (el, fn) {
var objChildNode = el.firstChild;
while (objChildNode) {
if (fn(objChildNode)) { // 返回 true 则删除
var next = objChildNode.nextSibling;
el.removeChild(objChildNode);
objChildNode = next;
} else {
if (objChildNode.nodeType === 1)
this.everyNode(objChildNode, fn);
objChildNode = objChildNode.nextSibling;
}
}
}
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Django 1.0 Template Development
Scott Newman / Packt / 2008 / 24.99
Django is a high-level Python web application framework designed to support the rapid development of dynamic websites, web applications, and web services. Getting the most out of its template system a......一起来看看 《Django 1.0 Template Development》 这本书的介绍吧!