ES6原生组件在页面频繁操作,导致页面崩溃,内存使用无异常。记一次奇葩BUG导致的页面崩溃

        最近在新项目中用了es6的window.customElements.define。组件使用过程中没发现任何问题,自测页面展示正常、操作正常,然后奇葩的现象来了,频繁切换多语言后,大概切换三四次,页面会出现卡顿的情况,主要表现为,接口请求发出去了,但实际上响应时间较长,页面一直pending.

        可以理解为,请求发出去了,但接口返回时间变长,当然,第一想法就是后端问题,让后端检查,检查后发现,后端没有任何问题。因为之前的原生组件已经上线了,并且影响了大概十几个用户,然后检查前端内存调用,方法等,没有发现任何比较特殊的现象,无奈下,只能将原生组件下掉,然后我当时盲目的定义是:es6原生组件某些情况下存在BUG,无法使用。后来想了想,觉得这种低级问题肯定不会存在已经制定为标准的规范上。

        因为我们的所有组件都是写成的NPM包,包的依赖又很多,实在不想本地导入。觉得没其他好办法了之后,我将组件的源文件直接引入了项目中,因为依赖的方法很多,我又把源文件中复制了一个新的,引入的方法直接在新文件中定义新的空方法,原则是只要组件展示正常,调用方法不报错就行了。

        然后就正常启动了项目,也按我的思路正常运行,我在所有可能触发崩溃的地方都打上log,观察哪个log会比较频繁的调用,或者哪个log加载不正常。然后就发现了一个很奇怪的现象:监听事件会频繁触发,大概是切换语言的几何倍数增加。

        原生组件使用的是es6的class,官网简单的DEMO如下,并且有个地方要注意,extends只能继承HTMLElement:

customElements.define(
  "element-details",
  class extends HTMLElement {
    constructor() {
      super();
      const template = document.getElementById(
        "element-details-template",
      ).content;
      const shadowRoot = this.attachShadow({ mode: "open" }).appendChild(
        template.cloneNode(true),
      );
    }
  },
);

然后再说一下我们组件的大概实现的思路:

1、在constructor下初始化方法,初始化方法做了两个事1)是将所有的按钮点击事件绑定到按钮上2)监听cookies变化时重新刷新dom结构,3)将dom结构插入

2、实现update方法,update方法跟1实现的思路是一样的,也是监听、绑定、插入

最后问题实际上也是出现了在这里,这个BUG出现也是我代码不严谨和不熟悉导致的,因为第一版代码是别的同事写的,就没很注意里面的实现。我想有的人可能已经发现问题,在update中还实现了监听和绑定,但update时没有将之前的绑定remove调,导致每次update都会重新监听N次,特别是cookies这个监听机制,主要是更新dom,几何次数增加。然后每次改多语言时其实只是更新了cookies,因为多语言(language)也是在cookies中存储的,导致最后1*2*3*4,最后监听了24次,然后在uodate的绑定事件,也是绑定了24次,cookies监听也至少监听了24次,导致主线程被严重的阻塞。

最后解决问题的思路也很简单,1)update只更新,DOM,但不重新监听,但这样有个问题,DOM更新后,ID的监听事件会失败 2)update时,先removeAddeventLister在add,这样其实也算是常规做法。

最后,澄清一下,es6的原生组件没有任何问题,但因为是全部基于原生写法,很多地方之前框架帮你做的事情都需要自己做,所以特别像监听事件、监听行为这种一定要做好事件的清除,不然会出现很难排查的BUG。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值