JavaScript对DOM操作的若干优化

很多人都认为JavaScript的效率太慢了,都不愿意用JavaScript来实现相对困难一点的程序逻辑。在这里我要说的是其实JavaScript的效率并不慢,慢的是DOM,如果操作好DOM,你的JS效率将提高接近千倍(这并不是什么夸张的数字)。

1. 批量增加Dom

尽量使用修改innerHTML的方式而不是用appendChild的方式; 因为使用innerHTML开销更小,速度更快,同时也更加内存安全.


有一点需要注意的是,用innerHTML方式添加时,一定不要在循环中使用 innerHTML += 的方式添加,这样反而会使速度减慢; 而是应该中间用array缓存起来,循环结束后调用 xx.innerHTML = array.join(”);的方式,或者至少保存到string中再插到innerHTML中.


针对用户列表一块采用这种方式优化后,加载速度提升一倍.



2. 单个增加Dom

这里是指要将新节点加载到一个内容不断变化的节点的情形,对于内容稳定的节点来说,随便怎么加都没有问题. 但是对于有动态内容的节点来说,为其添加子节点尽量使用 DOM append的方式.


这是因为,DOM append不会影响到其他的节点;而如果修改innerHTML属性的话,该父节点的所有子节点都会从DOM树中剥离,再根据新的innerHTML值来重绘子节点DOM树,所有注册到原来子节点的事件也会失效.
这点要特别注意,也就是说,本来子结点是有个事件的,你在父节点上搞个parentNode.innerHTML += ‘string’,那么本来有事件的那个子节点也就没有事件了。我们看看例子:


<html>
    <head>
        <meta charset="utf-8">
        <style type="text/css">
            #div1 {
                width: 500px;
                height: 500px;
                background: red;
            }
            #div2 {
                width: 400px;
                height: 400px;
                background: blue;
            }
            #div3 {
                width: 300px;
                height: 300px;
                background: orange;
            }
            #div4 {
                width: 220px;
                height: 220px;
                background: green;
            }
            li {
                list-style: none;
            }
            #innerUL li {
                border: 1px solid black;
            }
        </style>
    </head>

    <body>
        <div id="div1">
            <div id="div2">
                <div id="div3">
                    <div id="div4">
                        <ul id="myul">
                            <li>1111</li>
                            <li>2222</li>
                            <li>3333</li>
                            <li>4444</li>
                            <li id="li5">5555
                                <ul id="innerUL">
                                    <li>inner1</li>
                                    <li>inner2</li>
                                    <li>inner3</li>
                                    <li>inner4</li>
                                </ul>
                            </li>
                            <li>6666</li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>

    <script type="text/javascript">
        var div1 = document.getElementById('div1');
        var div4 = document.getElementById('div4');

        div1.onclick = function(ev) {
            var oEvent = ev || event;
            var target = oEvent.target || oEvent.srcElement;
            alert(target.id || target.innerText);
        };

        div4.onclick = function() {alert('----i am div4 -----');};
    </script>

    </body>
</html>

本来,我点击div4,是会弹出’—-i am div4 —–’的:


这里写图片描述


现在我们打开控制台,把div4当做子节点,那么在div3(父节点)里来个如下操作:


这里写图片描述


点击子节点div4,再也弹不出’—-i am div4 —–’了。当然了,事件委托是不受影响的。


下面这么写也是不行的,即使事件绑定在后面也不行。

这里写图片描述


综上,如果在一个有动态内容的节点上 出现了 innerHTML += ‘string’ 的代码,就该考虑是否有问题了.




3. 创建Dom节点

用 createElement方式创建一个dom节点,有一个很重要的细节: 在执行完createElement代码之后,应该马上append到dom树中,否则,如果在将这个孤立节点加载到dom树之前所做的赋值它的属性和innerHTML的操作都会引发该dom片段内存无法回收的问题. 这个不起眼细节,一旦遇到大量dom增删操作,就会引发内存的灾难.


4. 删除Dom节点

删除dom节点之前,一定要删除注册在该节点上的事件,不管是用observe方式还是用addEventListner方式注册的事件,否则将会产生无法回收的内存.


另外,在removeChild 和 innerHTML=” 二者之间,尽量选择后者. 因为在内存泄露监测工具中监测的结果是用removeChild无法有效地释放DOM节点.




5. 监听动态元素

Dom 事件默认是向上冒泡的,发生在子节点中的事件,可以由父节点来处理. event的 target/srcElement 仍是产生事件的最深层子节点。 这样,对于内容动态增加并且子节点都需要相同的事件处理函数的情况,可以把事件注册上提到父节点上。这样就不需要为每个子节点注册事件监听了。


同时,这样做也避免了产生无法回收的内存。即使是用Prototype的observe方式注册事件并在删除节点前调用stopObserving,也会产生出少量无法回收的内存,所以应该尽量少的为dom节点注册事件监听。


所以,当代码中出现在循环里注册事件时,也是我们该考虑事件上提机制的时候了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值