发表于: 2019-10-11 23:20:27
1 851
今日完成的事
完成弹窗组件,样式的调试
明日计划的事
继续任务
遇到的问题
解决之前的bug,在使用elementUI中的导航的时候,第一次点击没问题,多次点击同一个按钮的时候会报错
插入这行代码就可以了
代码初步判定是vue-router的问题,因为elementUI的导航栏使用了vue-router。
而vue-router在3.1.0 版本的路由跳转使用的是 promise 的方式,可能是因为vue的官方人员没设计好而造成了BUG。
github中3.11版本已经修复了这个bug,elementUI好像没有跟进
收获
vue的官方文档一直在告诫我们要减少dom操作,要按照数据驱动的思路来考虑程序,那么为什么要减少dom操作呢,因为操作DOM代价大、耗性能。
DOM其实就是一个javascript对象,每个DOM节点就是这个对象里面的属性。所以,操作DOM其实就是修改js对象的属性值(就好比:js.a = "b"),这个js对象改变后,会触发一些浏览器的行为,这个行为(比如layout和paint)就是代价大、耗性能的原因了。
首先浏览器层面渲染引擎工作的过程
解析HTML代码,生产DOM tree
解析CSS样式,结合DOM tree生产Render tree(display: none;的结点不会存在Render tree上,最后不会被paint)
计算Render tree各个节点的布局信息,比如box的位置、尺寸、颜色、外形等
根据计算后的布局信息,调用浏览器的UI引擎进行渲染。
上面的是欧朋浏览器的渲染过程
这是chrome的渲染流程
layout(布局)和paint(绘制)是代价最大的,layout就是布局变动造成重新计算(耗CPU,有时也很耗内存),paint就是调用浏览器UI引擎进行渲染展示页面(耗CPU和内存)。下面详细说下layout如何耗性能耗资源:
layout(布局),主要是计算文档中元素的位置、大小等信息,是渲染工作的第三步。
在HTML被加载时会进行layout,样式改变会导致layout,js执行的时候涉及到布局信息都会导致layout,估计这时候快疯了,那么多样式,每个样式、每个js都layout一次,岂不是一个页面要layout几百万次。。。浏览器还是精明的,对于layout行为是lazy的,不会傻到每个样式进行一次layout,对于CSS和JS都会把需要layout行为的数据缓存到一个队列中,当上下文完成执行后进行一次layout(css比如:结点的样式描述完。js比如:一个代码块执行完)。
浏览器的lazy会带来另外一个问题,layout信息在队列中的时候,我需要获取DOM节点信息就获取不到了,这时候浏览器就会提前执行一次layout,这就是DOM操作耗性能耗资源的罪魁祸首。
导致提前layout的常见情况:
1、通过js获取DOM属性
2、增/删/DOM节点
3、改变浏览器窗口大小
4、改变字体
5、激活css伪类
6、修改DOM的属性,涉及到大小、位置等(该颜色不会激活提前的layout)
7、其他js操作。。。
还有,特别重要的。。。动画的每一帧都会导致layout,为了减少动画带来的layout性能损失,可以动画元素绝对定位,使其脱离文本流。另外,requestAnimationsFrame也可以把layout积累后进行。另外,HTMLCollection对象最好缓存,否则layout次数将乘以数组的长度系数,还有就是减少DOM元素的嵌套深度,并优化CSS的深度。
假设DOM元素为5千,减少DOM操作,可以大大减少客户端的性能消耗,假如是手机端更为明显,如DOM操作太频繁,手机端会因内存爆满或CPU占用过度而出现浏览器闪退现象。
这还只是layout造成的性能问题。。。paint造成的性能问题同样严重。。。不过最近几年的硬件进步特别明显,以上操作的必要性所占的比重是否还那么重要就不得而知了。
评论