美文网首页实用前端让前端飞Web前端之路
前端性能提升+内存管理+事件委托

前端性能提升+内存管理+事件委托

作者: 麦壳儿UIandFE2 | 来源:发表于2017-04-27 17:19 被阅读109次

标签(空格分隔): 事件委托 冒泡 性能优化


序:

开启本文前,首先有几点要说明一下。
问题
1:添加到文档上的事件处理程序越多,页面整体运行性能越低。
2:每个函数都是对象,都要占内存,内存中的对象越多,性能越差,跑不动
3:页面一加载上来要事先指定DOM的事件处理程序,导致访问DOM的次数,进而延迟了整个文档的交互就绪时间。
所以:从以上的角度考虑:
解决
1》避免向页面中DOM添加大量的事件处理程序,限制了DOM和js建立连接的数量。利用委托,只是给某个祖级指定一个事件处理程序,来管理某一类的所有事件。例如:管理所有的点击。
2》对于即将移除的DOM,要手动移除其身上的事件处理程序。有些浏览器不会做只能处理释放掉,比如:通过innerHTML方式替换掉的元素。

方案一:利用委托

论证上边写的很清楚了,下面就是针对每个方案上一段代码吧。
HTML:

<div class="con">
    <button id="btn1">点击我变色</button>
    <p id="btn2">点击出弹窗</p>
    <h6 id="btn3">点击做跳转</h6>
</div>

CSS:

 .con {
            background: rgba(0, 0, 0, .2);
            border: 1px solid #ff9;
        }

.btn1, .btn2, .btn3 {
            width: 300px;
            height: 50px;
            border: 1px solid #000;
            text-align: center;
            line-height: 50px;
            cursor: pointer;
}

目标:
点击3个元素走不同的事件处理程序。

分析:
3个元素共同的祖级是类名叫.con的元素。所以把事件执行程序与他建立联系即可。而不是传统的给每个元素绑定一次事件处理代码。

实现:
JS:

  window.onload = function () {
//1:获取DOM
        var btn1 = document.querySelector('#btn1');
        var btn2 = document.querySelector('#btn2');
        var btn3 = document.querySelector('#btn3');
        var con = document.querySelector('.con');

//2:事件委托
        con.addEventListener('click', function (e) {
            var e = e || event;

            if (e.target.id == 'btn1') {
                //换背景色
                con.style.background = '#80B3FF';
            }
            if (e.target.id == 'btn2') {
                //弹出目标的id
                alert(e.target.id);
            }
            if (e.target.id == 'btn3') {
                //做跳转
                window.location.href = 'https://macrolam.github.io/MK/';
            }

        }, true)
    }

===================================================
tip:
这里是通过事件对象的里的target对象里的id属性,当然这种在实际开发事使用较少,毕竟要给每个元素一个id,id甚是宝贵,不能乱来,所以,再看看通过其他方式选中你要操作的元素。普通元素还可以通过节点名(标签名),标签内容。表单元素还可以通过name属性,例如这里的button按钮。标签身上设置下name属性。js里根据这个属性去拿到对应DOM。

===================================================

通过其他方式拿到对应的DOM

1.标签名:

HTML:

<div class="con">
    <button>点击我变色</button>
    <p>点击出弹窗</p>
    <h6>点击做跳转</h6>
</div>

这里省略样式,和上边一致的。.con里的子只有标签名字。

JS:

   window.onload = function () {
   
        var btn1 = document.querySelector('button');
        var btn2 = document.querySelector('p');
        var btn3 = document.querySelector('h6');

        var con = document.querySelector('.con');


        con.addEventListener('click', function (e) {
            var e = e || event;
     
            if (e.target.nodeName.toLowerCase() == 'button') {
                //换背景色
                con.style.background = '#80B3FF';
            }
            if (e.target.nodeName.toLowerCase() == 'p') {
                //弹出目标的id
                alert(e.target.nodeName);
                //二者是一致的
                alert(e.srcElement.nodeName);
            }
            if (e.target.nodeName.toLowerCase() == 'h6') {
                //做跳转
                window.location.href = 'https://macrolam.github.io/MK/';
            }

        }, true)
    }

e.target.nodeName拿到的是大写的标签名字,所以需要转换成小写好处理些。toLowerCase()一下就OK了。

2.标签内容:

HTML:

<div class="con">
    <button>点击我变色</button>
    <p>点击出弹窗</p>
    <h6>点击做跳转</h6>
</div>

JS:

   window.onload = function () {

        var con = document.querySelector('.con');

        con.addEventListener('click', function (e) {
            var e = e || event;
            if (e.target.innerHTML == '点击我变色') {
                //换背景色
                con.style.background = '#80B3FF';
            }
            if (e.target.innerHTML == '点击出弹窗') {
                //弹出目标的id
                alert(e.target.nodeName);
                //二者是一致的
                alert(e.srcElement.nodeName);
            }
            if (e.target.innerHTML == '点击做跳转') {
                //做跳转
                window.location.href = 'https://macrolam.github.io/MK/';
            }

        }, true)
    }

利用 e.target.innerHTML或者是e.target.innerText都可以。

3.表单标签的name属性:

如果是表单元素,还可以在表单元素上把name属性设置下。

HTML:

<div class="con">
    <button name="fromDomBtn">点击我变色</button>
    <p>点击出弹窗</p>
    <h6>点击做跳转</h6>
</div>

JS:这里只是写按钮部分了。

con.addEventListener('click', function (e) {
            var e = e || event;
            
            if (e.target.name == 'fromDomBtn') {
                //换背景色
                con.style.background = '#80B3FF';
            }
    }

利用表单身上的属性name;即e.target.name

常规处理方式就是以上几种,可以根据你的代码选择合适的方案。

方案二:手动移除事件处理程序

如果心里清楚,哪些带有事件处理程序的元素将要被移除,那么最好手动置空他的事件处理程序,即切断了DOM和js之间的引用关系。如果直接对DOM进行增删改查中的“删”,即:removeChild()/replaceChild()等,是不需要咱们手动再置空他们身上原来的事件引用。因为前端的代码一般不需要我们进行内存管理、垃圾回收等操作,浏览器会帮我们做好。这里说的将要被移除是指通过innerHTML的方式替换达到删除的结果,此时就需要我们做点事了,因为一些浏览器不会很好的处理这一块,例如(IE);下边用代码演示下具体怎么实现:

HTML:

<div class="con">
    <button>点击我发生con的内容替换</button>
</div>

JS:

  window.onload = function () {
        var con = document.querySelector('.con');
        var btn = document.querySelector('button');
        
        const txt = ` <h1>Lorem ipsum dolor.</h1>
    <p> Error esse est illo impedit libero molestias, perspiciatis ratione repudiandae voluptate voluptatem!</p>`;



        btn.onclick = function () {
            btn.onclick = null;//点击进来后手动释放自身和事件处理程序的引用关系;用过一次就释放掉了
            con.innerHTML = txt;
        }
    }

把这段代码,复制到你的编译器试试吧,点击事件肯定只会执行一次。

js库实现委托

如果你不是使用原生js,使用jQuery或是zepto等怎么做呢?更简单。直接上代码。

HTML片段截取:

    ![](/gameInfo/images/ban.jpg)
    <a href="###" class="loadBtn hrefTo"></a>
    <b class="clickDetail hrefTo">(点击了解详情)</b>

由于jQuery/zepto里自带的事件注册on方法只能接受3个参数,所以对于第二个参数DOM;要好好利用下了,把需要的做同一件事的dom都附属一个类名叫:hrefTo的。OK。

    //1:引入库
    <script src="/common/js/zepto.min.js"></script>
    //2:点击banner/了解详情/下载按钮三处实现跳转
    
    $('body').on('click','.hrefTo',function () {
        window.location.href="https://www.baidu.com/";
    });

----------------------------------------------------喜欢就动动小手哈。------------------------------------------------------

--------------------------------------你的支持是洒家-麦壳-macrolam前进的动力--------------------------------------

相关文章

  • 前端性能提升+内存管理+事件委托

    标签(空格分隔): 事件委托 冒泡 性能优化 序: 开启本文前,首先有几点要说明一下。问题1:添加到文档上的事件处...

  • JS-杂篇-18/4/7

    XMLHttpRequest请求 内存和性能 js事件处理程序数量将直接影响页面整体运行性能 事件委托 利用冒泡特...

  • Javascript中的事件委托与事件模拟

    内存和性能 事件类型是在太多了,直接跳到事件内存和型能这里 事件委托由于事件冒泡的原理,可以只盯一个事件处理程序,...

  • 第十六章 事件委托

    什么是事件委托 事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件 可以更加的节约性能...

  • JavaScript 性能优化

    介绍 性能优化是不可避免的哪些内容可以看做性能优化无处不在的前端性能优化 JavaScript内存管理 为什么要使...

  • 前端 - 事件委托

    事件委托,就是把事件委托给别人,让别人来帮自己完成。 注:本文 JavaScript 代码部分使用 jQuery ...

  • iOS性能优化

    目录 初学者性能提升 1. 用ARC管理内存 ARC(Automatic Reference Counting, ...

  • vue:巧用事件委托提升性能

    大量的事件处理函数会影响性能: 事件处理函数本质上是一种函数,是一种对象,存放在内存中,设置大量的事件处理函数会使...

  • 面试相关

    前端开发面试题(重要)看完这篇关于MVVM的文章,面试通过率提升了80%简述JS中的事件委托和事件代理

  • iOS性能调优之--内存管理

    iOS性能调优之--内存管理 iOS性能调优之--内存管理

网友评论

    本文标题:前端性能提升+内存管理+事件委托

    本文链接:https://www.haomeiwen.com/subject/sklnzttx.html