详解Vue依赖收集引发的问题


Posted in Javascript onApril 22, 2019

问题背景

在我们的项目中有一个可视化配置的模块,是通过go.js生成canvas来实现的。但是,我们发现这个模块在浏览器中经常会引起该tab页崩溃。开启chrome的任务管理器一看,进入该页面内存和cpu就会暴涨,内存经常会飙到700多M。但是我们的canvas实际的像素只有约500x500,根据一些粗略的计算,大概只占了1M的内存,这个计算过程可参考100*100的 canvas 占多少内存。那么我们这700M内存是哪里来的呢?

定位问题

我们可以使用chrome开发者工具来分析我们的调用栈。这边我是先通过Performance来帮助我们定位问题,它会帮我们生成一段过程中一些数据的变化,包括js堆内存、dom节点数量、动画帧等数据,如图:

详解Vue依赖收集引发的问题

这是切换至一个canvas画布较大的一个模块的performance分析表现,可以看到占用了472M的内存。下面折线图蓝色部分是js堆内存的变化,而Main下面黄色与紫色的矩形框就是我们的调用栈,上下两部分是按照时间一一对应的。可以看到,蓝色的折线呈高低起伏的态势,GC回收之后低点基本和高点持平,因此可以断定几乎不存在内存泄漏的问题。然后我们可以放大去看一看,内存升高的时候,js做了些什么事情,找一找规律。

 详解Vue依赖收集引发的问题

我们随机找一段内存增长的区域,可以看到在内存增长的过程中,最为频繁调用的就是Observer相关的代码。但是就这么看,我们不能够明白Observer是在干什么。此时我们可以借用Memory选项中的Allocation Sampling按照javascript function来查看内存分配,我们同样录制以上的一段操作。

详解Vue依赖收集引发的问题

此时我们能够清楚的看到,的确是这个Observer在作怪。同时,我们可以看到这是vue的代码,点击右边的文件查看source code,就可以清楚的明白这就是vue在执行依赖收集的操作,此时会给属性添加watcher。那我们这里为什么会有如此多的属性被添加了watcher呢?看了一下代码,原来是我把go.js的一个实例挂到了vue的data选项中,放到data中的属性会被vue执行依赖收集的相关操作,而这个实例拥有非常多的嵌套属性,全部都会被添加watcher。其实,我们只是想单纯的存储一下这个实例,供我们后续调用其相关的方法,添加watcher对我们来说完全没有意义,那我们如何避免这样的问题呢?

解决问题

上网搜索了相关的解决方案,大概有如下几种:

  1. 在data中定义的属性前面加上$,即通知vue该属性不需要被依赖收集,例如:javascript data() { return { $goDiagram: null } }但是这样声明,在template中引用时会报找不到$goDiagram属性的错误,具体的原因我还没深究,有空可以研究一下。
  2. 不在data中声明,直接在赋值的时候声明this.goDiagram = diagram。这同样会遇到第一种方案的问题,模板中会提示找不到goDiagram属性。
  3. 不在data中声明,而是利用$options来存储goDiagram,例如:
export default {
 goDiagram: null,
 mounted() {
  this.$options.goDiagram = xxx
 }
}

 这应该是比较好的一个方法,vue官方中也说明了$options用来包含自定义属性,例如我们平时引入的常量或是枚举类型,我们也不希望它们被添加无意义的watcher,因此可以通过这种方式来定义,在template中引用时只需要{{$options.xxx}}即可。这种方式唯一的缺点就是不能像data那样一眼望去就能清楚地知道你定义了什么属性。
项目中我采用了第一种方式,经过修改后内存占用量减少到原来的1/5到1/6,可以说效果非常好,再也不会出现浏览器崩溃的情况了。

总结

通过这样的一个问题,我们主要能够学习到两点:

  1. 如何通过chrome的开发者工具,去快速地定位代码中存在的内存问题
  2. 不要盲目的将属性都挂载到data选项中,一些常量我们可以采取上面提到的几种方式来定义,以此来作为一种优化手段

以上所述是小编给大家介绍的Vue依赖收集引发的问题详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JS 页面内容搜索,类似于 Ctrl+F功能的实现代码
Aug 13 Javascript
JSON 数据格式介绍
Jan 13 Javascript
面向对象继承实例(a如何继承b问题)(自写)
Jul 01 Javascript
jq实现酷炫的鼠标经过图片翻滚效果
Mar 12 Javascript
我的Node.js学习之路(二)NPM模块管理
Jul 06 Javascript
JavaScript实现垂直向上无缝滚动特效代码
Nov 23 Javascript
详解vue数据渲染出现闪烁问题
Jun 29 Javascript
Chrome调试折腾记之JS断点调试技巧
Sep 11 Javascript
微信小程序获取手机网络状态的方法【附源码下载】
Dec 08 Javascript
vue-cli2.9.3 详细教程
Apr 23 Javascript
利用js将ajax获取到的后台数据动态加载至网页中的方法
Aug 08 Javascript
基于Vue中的父子传值问题解决
Jul 27 Javascript
JS大坑之19位数的Number型精度丢失问题详解
Apr 22 #Javascript
Vue $mount实战之实现消息弹窗组件
Apr 22 #Javascript
深入理解vue中的slot与slot-scope
Apr 22 #Javascript
浅析vue插槽和作用域插槽的理解
Apr 22 #Javascript
详解50行代码,Node爬虫练手项目
Apr 22 #Javascript
Vue匿名插槽与作用域插槽的合并和覆盖行为
Apr 22 #Javascript
详解Vue 匿名、具名和作用域插槽的使用方法
Apr 22 #Javascript
You might like
PHP中HTTP方式下的Gzip压缩传输方法举偶
2007/02/15 PHP
删除html标签得到纯文本可处理嵌套的标签
2014/04/28 PHP
php判断数组中是否存在指定键(key)的方法
2015/03/17 PHP
详解PHP执行定时任务的实现思路
2015/12/21 PHP
prototype1.4中文手册
2006/09/22 Javascript
利用WebBrowser彻底解决Web打印问题(包括后台打印)
2009/06/22 Javascript
JQuery对class属性的操作实现按钮开关效果
2013/10/11 Javascript
js 阻止子元素响应父元素的onmouseout事件具体实现
2013/12/23 Javascript
DOM节点删除函数removeChild()用法实例
2015/01/12 Javascript
JS实现简单的右下角弹出提示窗口完整实例
2016/06/21 Javascript
vue 组件高级用法实例详解
2018/04/11 Javascript
vue中倒计时组件的实例代码
2018/07/06 Javascript
vue展示dicom文件医疗系统的实现代码
2018/08/27 Javascript
Swiper.js实现移动端元素左右滑动
2019/09/08 Javascript
vue实现简单学生信息管理
2020/05/30 Javascript
详尽讲述用Python的Django框架测试驱动开发的教程
2015/04/22 Python
Python实现求数列和的方法示例
2018/01/12 Python
python xlsxwriter创建excel图表的方法
2018/06/11 Python
python 读取.csv文件数据到数组(矩阵)的实例讲解
2018/06/14 Python
python自带tkinter库实现棋盘覆盖图形界面
2019/07/17 Python
对python中url参数编码与解码的实例详解
2019/07/25 Python
详细整理python 字符串(str)与列表(list)以及数组(array)之间的转换方法
2019/08/30 Python
动态设置django的model field的默认值操作步骤
2020/03/30 Python
Scrapy模拟登录赶集网的实现代码
2020/07/07 Python
Python Web项目Cherrypy使用方法镜像
2020/11/05 Python
利用python+ffmpeg合并B站视频及格式转换的实例代码
2020/11/24 Python
matplotlib bar()实现多组数据并列柱状图通用简便创建方法
2021/02/24 Python
HTML5里autofocus自动聚焦属性使用介绍
2016/06/22 HTML / CSS
Canvas系列之滤镜效果
2019/02/12 HTML / CSS
浅谈HTML5新增和废弃的标签
2019/04/28 HTML / CSS
英国领先的鞋类零售商:Shoe Zone
2018/12/13 全球购物
餐饮商业计划书范文
2014/04/29 职场文书
毕业证明模板
2015/06/19 职场文书
全家福照片寄语怎么写?
2019/04/02 职场文书
Python趣味挑战之教你用pygame画进度条
2021/05/31 Python
详解JAVA的控制语句
2021/11/11 Java/Android