遍历 DOM 注意点
栏目: JavaScript · 发布时间: 5年前
内容简介:版权声明:本文为博主原创文章,未经博主允许不得转载。 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; } } }
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 数组常见的遍历循环方法、数组的循环遍历的效率对比
- C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows VirtualStudio)——遍历和删除
- Js遍历数组总结
- 遍历
- MySQL 实现树形的遍历
- golang之树的遍历
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
国际游戏设计全教程
[美]迈克尔·萨蒙德 / 张然、赵嫣 / 中国青年出版社 / 2017-2 / 108.00元
你想成为一名电子游戏设计师吗?想知道《肯塔基0号路》《到家》《枪口》等独立游戏的制作理念及过程吗?想了解《戈莫布偶大冒险》《辐射3》《战争机器》中关卡设计的奥秘吗?本书用通俗易懂的文字介绍了在游戏开发与策划过程中,需要掌握的游戏设计原理和制作的基础知识,可以作为读者从“构思一个电子游戏”到“真正完成一个电子游戏”的完备指南。 本书以系统的游戏设计流程结合大量优秀的游戏设计案例进行讲解,让读者......一起来看看 《国际游戏设计全教程》 这本书的介绍吧!
在线进制转换器
各进制数互转换器
XML、JSON 在线转换
在线XML、JSON转换工具