Jquery dom查找方法 性能分析

来源:互联网 发布:淘宝正道体育 编辑:程序博客网 时间:2024/05/19 04:56

每次要动笔写一篇文章时,才发现需要准备的很多很多,原本只想记录一个小点,但一要写文章就会发现能牵扯出一大面来,再次验证了:基础很重要!本文只记录笔者近期开发中遇到的jquery dom基本查找方法,然后将各种方法性能做了一个比较,目的是希望自己在以后dom元素查找时,使用最优的方案。

jquery为遍历dom结点操作提供了丰富的方法:children()、next()、nextAll()、prev()、prevAll()、siblings()、closest()等,可自行搜索jquery之dom基础操作相关资料。因此,我们如果想要操作某一元素的父子及兄弟元素会有各种各样的渠道,笔者以自己在移除dom时,清除dom中所有绑定事件过程为例,验证几种dom遍历方法的性能情况,代码如下:

html:

<span style="font-size:14px;"><div class="conditionGroup">    <div class="orDivOut"><div class="orDivBr"></div><div class="orDiv orDivText">or</div>    </div>    <div class="ruleAddCondition"><input type="text" class="form-control valid appDll"/><div class="and-condition-parent">         <div class="addConditionBr"></div>         <div class="addInner">         <div class="addDiv">and</div>             <input type="text" class="form-control valid appSubDll" />              <input type="text" class="form-control valid conditionalDll" />              <input type="text" class="form-control valid valueTxt" />           </div>      </div>    </div></div></span>

js:

<span style="font-size:14px;">//遍历dom移除事件console.time("集合遍历"); for(var i=0;i<30;i++){$that.closest("div.conditionGroup").find(".remove-and,.remove-condition").off("click");$that.closest("div.conditionGroup").find(".appSubDll,.appDll,.conditionalDll").off("change");}console.timeEnd("集合遍历");console.time("依次父子方式遍历"); for(var i=0;i<30;i++){$that.off("click");$that.closest("div.conditionGroup").find(".remove-and").off("click");$that.closest("div.conditionGroup").find(".appSubDll").off("change");$that.closest("div.conditionGroup").find(".appDll").off("change");$that.closest("div.conditionGroup").find(".conditionalDll").off("change");$that.closest("div.conditionGroup").find(".addConditionBtnDiv").off("change");}console.timeEnd("依次父子方式遍历");console.time("全部遍历"); for(var i=0;i<30;i++){$that.closest("div.conditionGroup").find("*").off("click").off("change");}console.timeEnd("全部遍历");console.time("依次兄弟方式遍历"); for(var i=0;i<30;i++){$that.off("click");$that.nextAll(".appDll").off("change");$that.nextAll(".and-condition-parent").find(".remove-and").off("click");$that.nextAll(".and-condition-parent").find(".appSubDll").off("change");$that.nextAll(".and-condition-parent").find(".conditionalDll").off("change");$that.nextAll(".div-add-condition-add").find(".addConditionBtnDiv").off("click");}console.timeEnd("依次兄弟方式遍历");console.time("变量暂存方式"); var $domTmp=$that.nextAll(".and-condition-parent");for(var i=0;i<30;i++){$that.off("click");$that.nextAll(".appDll").off("change");$domTmp.find(".remove-and").off("click");$domTmp.find(".appSubDll").off("change");$domTmp.find(".conditionalDll").off("change");$domTmp.nextAll(".div-add-condition-add").find(".addConditionBtnDiv").off("click");}console.timeEnd("变量暂存方式");console.time("链式遍历"); for(var i=0;i<30;i++){$that.off("click").nextAll(".appDll").off("change").nextAll(".and-condition-parent").find(".appSubDll").off("change").nextAll(".conditionalDll").off("change").nextAll("remove-and").off("click").closest(".and-condition-parent").nextAll(".div-add-condition-add").find(".addConditionBtnDiv").off("click");}console.timeEnd("链式遍历");</span>
操作场景为点击容器中删除按钮,删除容器并移除容器中所有绑定事件。遍历dom结点过程体现在根据删除按钮,依次查找有绑定事件的dom元素,根据笔者常规使用的和常规思路想到的汇总了上述几种方法:

1、集合遍历:找到容器根,一次性根据要查找的元素依据进行目标dom查找。个人开始想法:写法上简化了不少,性能应该比一个一个的去遍历要好吧?

2、依次父子方式遍历:找到容器根,依次使用find查找目标元素。个人开始想法:这个应该不如上一个,至少这个遍历次数是不是多了?

3、全部遍历:干脆不要提供目标dom的依据了,全部遍历一遍,所有dom都执行卸载事件过程,没有事件也没关系。个人开始想法:写法简便许多,逻辑简化,应该只遍历一遍,性能应该不错吧?

4、依次兄弟方式遍历:根据删除按钮,以nextAll(兄弟)查找方式,依次查找目标dom。个人开始想法:不需要找到根从头遍历,应该比2好些吧?

5、变量暂存方式:依次查找时,多次使用的dom通过变量暂存。个人想法:这种写法多余,理论就应该这样做,这应该是开发规范的行列了,姑且就写出来对比一下时间上能差多少吧,这个性能一定是最好把?

6、链式遍历:不需要每次从跟遍历,按照元素的位置,层级,依次链式写下去。个人开始想法:部分元素不需要从头遍历,减短了遍历长度,性能应该比从根好吧?

多实践几次,看结果:




实验证明:依次父子方式、变量暂存方式性能较优。即此情景下,find由于nextAll,至于各种方法的遍历过程笔者还不是很清晰,需要继续摸索。但上述实践中,依次父子与变量暂存方式,区别不大,有些不符合常理,应该变量暂存方式快得多才对,再看一遍发现此处变量暂存并非父子查找方式,因此增加以下方法,再次实验:
<span style="font-size:14px;">console.time("变量暂存方式1"); var $domTmp=$that.nextAll(".and-condition-parent");for(var i=0;i<30;i++){$that.off("click");$that.nextAll(".appDll").off("change");$domTmp.find(".remove-and").off("click");$domTmp.find(".appSubDll").off("change");$domTmp.find(".conditionalDll").off("change");$domTmp.nextAll(".div-add-condition-add").find(".addConditionBtnDiv").off("click");}console.timeEnd("变量暂存方式1");console.time("变量暂存方式2"); var $domTmp=$that.closest("div.conditionGroup");for(var i=0;i<30;i++){$that.off("click");$domTmp.find(".appDll").off("change");$domTmp.find(".remove-and").off("click");$domTmp.find(".appSubDll").off("change");$domTmp.find(".conditionalDll").off("change");$domTmp.find(".addConditionBtnDiv").off("click");}console.timeEnd("变量暂存方式2");</span>
结果:

很明显变量暂存方式快了很多。

经过以上试验,可总结出此情景下通过根,find方式性能较好。但并非绝对,笔者猜测这与目标元素的位置及容器中dom元素总数都有关系。因此还是应该把每种方法dom遍历的具体过程了解清楚才是根本掌握...

个人拙见,还望各位给与指导...

0 0