详解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 相关文章推荐
用javascript自动显示最后更新时间
Mar 15 Javascript
JavaScript 字符串乘法
Aug 20 Javascript
JavaScript中Object和Function的关系小结
Sep 26 Javascript
javascript数字数组去重复项的实现代码
Dec 30 Javascript
使用OpenLayers3 添加地图鼠标右键菜单
Dec 29 Javascript
BootStrap智能表单实战系列(十一)级联下拉的支持
Jun 13 Javascript
深入理解AngularJS中的ng-bind-html指令和$sce服务
Sep 08 Javascript
聊一聊JS中的prototype
Sep 29 Javascript
vue结合Echarts实现点击高亮效果的示例
Mar 17 Javascript
基于jquery实现的tab选项卡功能示例【附源码下载】
Jun 10 jQuery
vue实现绑定事件的方法实例代码详解
Jun 20 Javascript
vue接口请求加密实例
Aug 11 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
smarty模板中拼接字符串的方法
2014/02/14 PHP
PHP中使用Memache作为进程锁的操作类分享
2015/03/30 PHP
php和editplus正则表达式去除空白行
2015/04/17 PHP
PHP实现多文件上传的方法
2015/07/08 PHP
PHP内核学习教程之php opcode内核实现
2016/01/27 PHP
yii2分页之实现跳转到具体某页的实例代码
2016/06/02 PHP
ThinkPHP框架实现的邮箱激活功能示例
2018/06/15 PHP
php常用字符串查找函数strstr()与strpos()实例分析
2019/06/21 PHP
javascript确认框的三种使用方法
2013/12/17 Javascript
基于jQuery实现搜索关键字自动匹配功能
2020/03/26 Javascript
javascript正则表达式之分组概念与用法实例
2016/06/16 Javascript
ajax的分页查询示例(不刷新页面)
2017/01/11 Javascript
jQuery插件echarts实现的多折线图效果示例【附demo源码下载】
2017/03/04 Javascript
详解基于angular-cli配置代理解决跨域请求问题
2017/07/05 Javascript
Vue 实现树形视图数据功能
2018/05/07 Javascript
讲解vue-router之什么是编程式路由
2018/05/28 Javascript
Vue插件打包与发布的方法示例
2018/08/20 Javascript
webpack4+react多页面架构的实现
2018/10/25 Javascript
Vue+Express实现登录注销功能的实例代码
2019/05/05 Javascript
JS使用正则表达式判断输入框失去焦点事件
2019/10/16 Javascript
Vue CLI3移动端适配(px2rem或postcss-plugin-px2rem)
2020/04/27 Javascript
vue实现在线学生录入系统
2020/05/30 Javascript
JavaScript实现商品评价五星好评
2020/11/30 Javascript
[43:18]NB vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.22
2019/09/05 DOTA
Python复制Word内容并使用格式设字体与大小实例代码
2018/01/22 Python
详解python3中用HTMLTestRunner.py报ImportError: No module named 'StringIO'如何解决
2019/08/27 Python
CSS3实现鼠标悬停显示扩展内容
2016/08/24 HTML / CSS
AmazeUI折叠式卡片布局,整合内容列表、表格组件实现
2020/08/20 HTML / CSS
给分销商的致歉信
2014/01/14 职场文书
幼儿园秋游活动方案
2014/01/21 职场文书
党的群众路线教育实践活动整改落实情况报告
2014/10/28 职场文书
golang中的空接口使用详解
2021/03/30 Python
撤回我也能看到!教你用Python制作微信防撤回脚本
2021/06/11 Python
Python探索生命起源 matplotlib细胞自动机动画演示
2022/04/21 Python
python神经网络 tf.name_scope 和 tf.variable_scope 的区别
2022/05/04 Python
正则表达式基础与常用验证表达式
2022/06/16 Javascript