记录基于vue在我的真实项目中的性能优化

最近一段时间一直在处理公司的一个内部项目哈,因为页面卡的问题被吐槽了一个月了。因为是接手别人的项目,虽然说不是自己直接造成的。但是解决这个问题已是迫在眉睫了。

可能我们在做前端开发的时候,很少去关注内存的问题,这是因为JS有自己垃圾回收机制,如果代码不是滥用闭包,一般来说,不会出现性能问题。


记录基于vue在我的真实项目中的性能优化

先来大概说下我的项目中性能瓶颈的现象:项目是一个基于electron+vue的一个类似微信桌面端的项目,因为是公司项目就不截图了,想象是微信就行了。

当我们切换左侧联系人列表的时候,发现内存不断的上升,而且很难降下来,很典型的内存泄露了。

时间一长,内存吃完了,程序直接崩了。。。

好吧,解决问题吧,知道有内存泄露,我们一般会找项目中的代码是不是有没有及时释放的闭包局部变量。

但是,效果不明显。

我的解决方案

1、查看当前页面的dom节点数。

一般来说在3000左右是为正常吧。这个如果查看呢?

很简单,我们只需要在浏览器控制台输入:

$$("*")

即可!


记录基于vue在我的真实项目中的性能优化

当我在我的项目中输入的时候,节点达到了10000+了,好家伙,问题找到了,原来是dom渲染太多了?

这应该是一个瓶颈吧,接下来不是去掉多余的dom了,我发现在渲染列表的时候,一些很多的原点是没有必要时时渲染的,还有一些dom是通过v-show来隐藏起来的。

慢慢的把这些问题解决了,dom节点降下来了。内存是得到了很好的控制。

你们以为这就完了吗?

但是随着列表的切换,内存还是会上升,只是没那么明显了。

What??

你们说气人不?没办法,还得继续优化了。

这时候,我们要结合我的第一种方案,形成第二种方案。

2、优化渲染列表本身。

一般来说,我们列表的数据是通过后端或者本地数据库获取到的一个数组对象,而数组的每一项一般都是一个Json对象。我们是直接将这个数据对象挂载到组件的data对象或者vuex中去。

不管是哪种方案,在读过vue源码后,知道他是存在一问题的。

首先,我们的组件的data对象下数据,vue为了双向数据绑定,会给每一个属性添加get和set函数。也就是说。一个数据对象所有的属性都会添加一次get和set,但是如果说我们的列表中的数据不需要数据响应,那这个get和set是没有意义的。

好了,有这个思路,我们应该要想办法不让vue去给这个列表数据添加get和set。那该怎么做呢?

要么说阅读源码很重要呢?因为我之前看过数据响应的相关源码哈,我就直接带大家看一眼吧。


记录基于vue在我的真实项目中的性能优化


在defineReactive方法中,它是专门用来定义get和set的,我们可以看到有一个情况他是不进行get和set的,当对象的configable为false的时候。

一般来说,一个对象的configurable属性为false的时候。

好像看到希望了

在ES5中,Object对象下有一个方法可以!!!

Object.freeze ,它可以将一个对象冻结起来。


记录基于vue在我的真实项目中的性能优化

当我们用Object.freeze将对象冻结的时候,我们再来看效果


记录基于vue在我的真实项目中的性能优化

结果一目了然了吧。

好了,接下来我们将我们要渲染的列表用Object.freeze来冻结。再来看效果。

果不其然,内存下来了,正常了。。。哈哈哈


问题来了,当我们把对象冻结后,如果我们想去修改数组中的某一项的数据的时候,这时候我们是无法直接修改的。这时候,我们需要先将冻结后的数组拿到,然后通过[...list];进行解冻。然后修改,然后将新的数组重新冻结再去更新data或者 vuex! 完美解决。


记录基于vue在我的真实项目中的性能优化

技术总结:

在排查问题的同时,我先考虑了本地数据库的性能问题,排除后再去排查ui的问题。

我们在vue项目开发的时候,一定要注意我们看不到的页面不要渲染无效的dom结构,要想提高列表的渲染性能,Object.freeze能大大帮助们提高页面性能。

从排查问题,到解决问题,过程是痛苦的,但是当问题被解决的时候,被用户肯定的时候,这些都值了。。

您可能还会对下面的文章感兴趣: