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

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


序:

开启本文前,首先有几点要说明一下。
问题
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前进的动力--------------------------------------

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 前端开发面试知识点大纲: HTML&CSS: 对Web标准的理解、浏览器内核差异、兼容性、hack、CSS基本功:...
    秀才JaneBook阅读 2,344评论 0 25
  • 每一次相爱都是那么简单, 而分手却是痛心的无奈。 好像每一次都是梦境的过往, ...
    微诗人阅读 314评论 0 1
  • 对“淋漓”这个词有感大约是看了《按自己的意愿过一生》,这种将自己有限的生命撑大到淋漓尽致的状态让人羡慕,同样也...
    羽然说阅读 722评论 0 1
  • 何处古琴暗飞声,散入秋风满城南。 八月十六,空气中飘着些许雨丝和淡淡的桂花香,我的心情如同这飘飘漾漾的花香...
    多肉多智阅读 682评论 0 2