Vue.js中轻松解决v-for执行出错的三个方案


Posted in Javascript onJune 09, 2017

前言

Vue.js 是开源的一个前端开发库,通过简洁的 API 提供高效的数据绑定和灵活的组件系统。在前端纷繁复杂的生态中,Vue.js在近年来受到一定程度的关注,目前在 GitHub上已经有5000+。

本文是笔者在开发实践中踩过的坑,总结和分享出来,希望对大家学习Vue有所帮助。下面来看看详细的介绍:

【问题描述】

v-for遍历数组中存在空值导致页面报错,情况如下:

Vue.js中轻松解决v-for执行出错的三个方案

开发框架是以Vue为模型绑定的核心,根据错误可以进行一个简单的判断:

      ▪ removeChild操作既然不是发生在开发者显示书写的代码中,就应该是模型销毁后Vue引擎移除dom节点导致的。

      ▪ 错误栈信息都在框架的代码之内,此操作不可能是有用户代码触发导致的。

开发者某一流程的操作,会100%稳定地触发出这一错误,此错误导致js执行终端,整个程序陷入瘫痪无法工作,开发者的操作流程可以简化为如下的步骤:

      1. 访问视图A。

      2. 访问视图B。

      3. 回退历史记录到A。(错误发生在这里)

以上的跳转关系都是视图跳转,也就是发生在路由系统之内的路由跳转,按照路由逻辑,第三步的时候会依次执行视图的声明周期函数,包括:

      ▪ B视图的unRender逻辑,包括beforeUnRender和afterUnRender。

      ▪ A视图的Render,包括beforeRender和afterRender。

开发者只在beforeRender的阶段进行了模型重置的操作,几乎可以确定无疑,报错就是由这几行模型重置和赋值的操作引起的。层层排除可以寻找到使用简单代码重新此问题的方式。

【重现方式】

准备一个简单的空工程,新建视图test,一下的代码分别为js/view/test.js和html/view/test.html,js/view/test.js中视图对模型的操作可以完整反映重现此问题的流程。其中,setTimeout模拟的是ajax操作以让数据在多个tick之后设置到模型以观察Vue对dom节点的创建和销毁。

$nextTick之后,将test_arr置空的操作是为了使vue将此数据对应的dom节点销毁,对应代码如下:

Vue.js中轻松解决v-for执行出错的三个方案

以上的代码可以稳定重新问题,下面是解题思路。

【解决方案】

在不求甚解的状态下,这个问题是比较容易解决的,这里有几个临时的解决方案。

▲方案一

从报错信息Uncaught TypeError: Cannot read property 'removeChild' of null可知,之所以发生这个问题是因为在null的对象上执行了removeChild。

修改Vue框架代码,将这里的代码:

Vue.js中轻松解决v-for执行出错的三个方案

修改为:

Vue.js中轻松解决v-for执行出错的三个方案

▲方案二

深入地分析,为什么el.parentNode会是null,通过上面重现的步骤发现,当that.model.test_arr = ["","4","","5","6",""]这段代码设置发生后,v-for产生的dom节点之后3个,而不是5个,这种情况下el.parentNode就是不存在的,所以产生了第二种解决方案,强制不给空数据的元素生成dom节点。

Vue.js中轻松解决v-for执行出错的三个方案

▲方案三

问题并不算是圆满解决,正常的情况下框架应该具有鲁棒性,适应不同的使用场景,不应该出现js报错的问题,所以还有深入研究下去的必要。

在Vue中针对v-for指令有一个track-by的可选配置:

       ▪无track-by情况:数据修改时,无论值是否被修改,dom都被重新渲染。

       ▪有track-by情况:数据修改时,不变数据所在的dom不被重新渲染,已改变的数据所在dom才被重新渲染。

因为 v-for 默认通过数据对象的特征来决定对已有作用域和 DOM 元素的复用程度,这可能导致重新渲染整个列表。但是,如果每个对象都有一个唯一 ID 的属性,便可以使用 track-by 特性给 Vue 一个提示,Vue因而能尽可能地复用已有实例。所以就有了第三种解决方案。

Vue.js中轻松解决v-for执行出错的三个方案

【原因分析】

v-for遍历数组中存在空值导致页面报错,主要是遍历条件里对值的判断有问题。Vue为了保证对dom节点的复用,内置了一份按照id存取的dom缓存,通过对数据分析出dom_id,然后根据此id从缓存中获取dom节点。由于不同的数据取到了相同的dom_id,所以没有创建dom节点出来。但是,在最终数组置空,模型变更之后dom节点移除的时候却为这些dom节点触发了remove操作,也就是方案一中兼容的那些代码:

Vue.js中轻松解决v-for执行出错的三个方案

所以问题必定出现在getTrackByKey这个函数的执行上,以下是getTrackByKey的代码:

Vue.js中轻松解决v-for执行出错的三个方案

Vue中对数据绑定的操作大大地提高了开发者应用开发的效率,但与此同时也伴随着一些不易察觉的问题,尤其如本文中问题的重现条件比较复杂的情况下,测试不一定可以覆盖到问题的触发条件,这个时候就需要开发人员多一分警惕。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
javascript中巧用“闭包”实现程序的暂停执行功能
Apr 04 Javascript
基于jquery实现的一个选择中国大学的弹框 (数据、步骤、代码)
Jul 26 Javascript
JS日期和时间选择控件升级版(自写)
Aug 02 Javascript
一款简单的jQuery图片标注效果附源码下载
Mar 22 Javascript
Angularjs 制作购物车功能实例代码
Sep 14 Javascript
jquery做个日期选择适用于手机端示例
Jan 10 Javascript
vue 1.x 交互实现仿百度下拉列表示例
Oct 21 Javascript
Vue.js与 ASP.NET Core 服务端渲染功能整合
Nov 16 Javascript
Angularjs Ng_repeat中实现复选框选中并显示不同的样式方法
Sep 12 Javascript
javascript跳转与返回和刷新页面的实例代码
Nov 20 Javascript
vue制作抓娃娃机的示例代码
Apr 17 Javascript
Vue两种组件类型:递归组件和动态组件的用法
Aug 06 Javascript
node.js中cluster的使用教程
Jun 09 #Javascript
vue bootstrap小例子一枚
Jun 09 #Javascript
详解webpack解惑:require的五种用法
Jun 09 #Javascript
Bootstrap输入框组件使用详解
Jun 09 #Javascript
Jquery+Ajax+xml实现中国地区选择三级联动菜单效果(推荐)
Jun 09 #jQuery
微信分享调用jssdk实例
Jun 08 #Javascript
浅谈vue实现数据监听的函数 Object.defineProperty
Jun 08 #Javascript
You might like
DEDE采集大师官方留后门的删除办法
2011/01/08 PHP
PHP文件缓存类示例分享
2015/01/30 PHP
PHP 在数组中搜索给定的简单实例 array_search 函数
2016/06/13 PHP
php通过header发送自定义数据方法
2018/01/18 PHP
JavaScript null和undefined区别分析
2009/10/14 Javascript
Extjs中常用表单介绍与应用
2010/06/07 Javascript
JavaScript移除数组元素减少长度的方法
2013/09/05 Javascript
jQuery $命名冲突解决方案汇总
2014/11/13 Javascript
js关于命名空间的函数实例
2015/02/05 Javascript
原生js结合html5制作小飞龙的简易跳球
2015/03/30 Javascript
JS中的二叉树遍历详解
2016/03/18 Javascript
Linux下为Node.js程序配置MySQL或Oracle数据库的方法
2016/03/19 Javascript
JQuery控制图片由中心点逐渐放大效果
2016/06/26 Javascript
微信小程序中的onLoad详解及简单实例
2017/04/05 Javascript
浅谈基于Vue.js的移动组件库cube-ui
2017/12/20 Javascript
vue 实现把路由单独分离出来
2020/08/13 Javascript
Vue如何将页面导出成PDF文件
2020/08/17 Javascript
uniapp微信小程序实现一个页面多个倒计时
2020/11/01 Javascript
[54:33]2018DOTA2亚洲邀请赛小组赛 A组加赛 Liquid vs Optic
2018/04/03 DOTA
Python发送form-data请求及拼接form-data内容的方法
2016/03/05 Python
Python可变参数用法实例分析
2017/04/02 Python
Python基于递归算法实现的走迷宫问题
2017/08/04 Python
Python通过matplotlib绘制动画简单实例
2017/12/13 Python
python将.ppm格式图片转换成.jpg格式文件的方法
2018/10/27 Python
pytorch实现用Resnet提取特征并保存为txt文件的方法
2019/08/20 Python
tensorflow -gpu安装方法(不用自己装cuda,cdnn)
2020/01/20 Python
keras小技巧——获取某一个网络层的输出方式
2020/05/23 Python
python判断是空的实例分享
2020/07/06 Python
html5 Canvas画图教程(4)—未闭合的路径及渐变色的填充方法
2013/01/09 HTML / CSS
采购主管工作职责
2013/12/12 职场文书
应届大学生简历中的自我评价
2014/01/15 职场文书
大学生党员批评与自我批评范文
2014/10/14 职场文书
2015年国庆节活动总结
2015/03/23 职场文书
个人借条范本
2015/05/25 职场文书
工商局调档介绍信
2015/10/22 职场文书
Win10 最新稳定版本 21H2开始推送
2022/04/19 数码科技