记录一次升级ant-design-vue的遇见的bug
记录一次升级ant-design-vue的遇见的bug
使用版本:
"version": "2.5.2"
"ant-design-vue": "1.4.2",
vue模板内容
<template>
<div>
<a-table :columns="columns" :dataSource="data" :rowSelection="rowSelection" :locale="{emptyText:'sdfsd'}"/>
</div>
</template>
<script>
export default {
data() {
return {
data:[ {
key: 1,
address: 'New York No. 1 Lake Park',
}] ,
columns: [
{
title: 'Address',
dataIndex: 'address',
width: '100%',
key: 'address',
},
],
rowSelection:{
onChange: () => {},
onSelect: () => {},
onSelectAll: () => {},
}
};
},
};
</script>
chrome控制台显示如下:

打开Sources看到是_traverse方法报错
function _traverse (val, seen) {
var i, keys;
var isA = Array.isArray(val);
if ((!isA && !isObject(val)) || !Object.isExtensible(val)) {
return
}
if (val.__ob__) {
var depId = val.__ob__.dep.id;
if (seen.has(depId)) {
return
}
seen.add(depId);
}
if (isA) {
i = val.length;
while (i--) { _traverse(val[i], seen); }
} else {
keys = Object.keys(val);
i = keys.length;
while (i--) { _traverse(val[keys[i]], seen); }
}
}
该方法存在于vue项目src/core/observer/traverse.js中,
traverse 的逻辑也很简单,它实际上就是对一个对象做深层递归遍历,因为遍历过程中就是对一个子对象的访问,会触发它们的 getter 过程,这样就可以收集到依赖,也就是订阅它们变化的 watcher
下面的代码就会触发traverse:
watch: {
a: {
deep: true, // deep属性为true是关键
handler(newVal) {
console.log(newVal)
}
}
}
在 watcher 执行 get 求值的过程中有一段逻辑:
get() {
let value = this.getter.call(vm, vm)
// ...
if (this.deep) {
traverse(value)
}
}
在traverse中打断点,打印出递归的traverse的参数name,发现异常:

如果深度遍历一个vnode节点,每一个vnode都保存有父节点和子节点的引用,遍历所有的vnode确实会导致栈溢出,但是怎么会遍历到一个vnode节点呢?
再看前面遍历到的一个对象,在ant-design-vue文档中查到是渲染rowSelection用到的,于是在ant-desing-vue的源码查到了 renderRowSelection方法:
renderRowSelection: function renderRowSelection(prefixCls, locale) {
......
selectionColumn.title = selectionColumn.title
|| h(SelectionCheckboxAll, {
attrs: {
store: this.store,
locale: locale,
data: data,
getCheckboxPropsByItem: this.getCheckboxPropsByItem,
getRecordKey: this.getRecordKey,
disabled: checkboxAllDisabled,
prefixCls: prefixCls,
selections: rowSelection.selections,
hideDefaultSelections: rowSelection.hideDefaultSelections,
getPopupContainer: this.generatePopupContainerFunc()
},
on: {
'select': this.handleSelectRow
}
});
......
SelectionCheckboxAll组件的locale属性就包含了emptyText,filterReset等,找到了位置,调试一下在renderTable中发现如下代码:
// locale至少是一个空对象
var locale = _extends({}, contextLocale, this.locale);
if (!locale || !locale.emptyText) {
mergedLocale.emptyText = renderEmpty(h, 'Table');
}
......
var columns = this.renderRowSelection(prefixCls, mergedLocale);
问题在于如果locale,经过排查international的LocaleReceiver.js,发现locale中有数据,又不存在emptyText字段,导致emptyText赋值为renderEmpty方法返回的组件,渲染SelectionCheckboxAll组件的时候,对属性遍历就会报栈溢出。
解决方案比较简单:给a-table组件加一个locale属性,同时locale的属性emptyText不为空。
之前的项目中为什么没有报错?
经过对比package.json和node_modules中的版本,发现旧项目ant-design-vue的版本是1.2.4,回退回去之后,问题消失了。
官网上为什么能够正常使用呢?
自己下载了一个浏览器版本的vue和antd-vue,测试正常,怀疑是vue版本的问题,对比了traverse方法
function _traverse (val: any, seen: SimpleSet) {
let i, keys
const isA = Array.isArray(val)
if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) {
return
}
if (val.__ob__) {
const depId = val.__ob__.dep.id
if (seen.has(depId)) {
return
}
seen.add(depId)
}
if (isA) {
i = val.length
while (i--) _traverse(val[i], seen)
} else {
keys = Object.keys(val)
i = keys.length
while (i--) _traverse(val[keys[i]], seen)
}
}
多了 val instanceof VNode这句判断,问题就解决了。
看看vue升级记录:
fix: do not traverse VNodes when regsitering dependencies
最终的解决方案:升级vue版本到2.6.x.
本文结束
记录一次升级ant-design-vue的遇见的bug的更多相关文章
- 基于Ant Design Vue封装一个表单控件
开源代码 https://github.com/naturefwvue/nf-vue3-ant 有缺点本来是写在最后的,但是博文写的似乎有点太长了,估计大家没时间往下看,于是就把有缺点写在前面了,不喜 ...
- Ant Design Vue select下拉列表设置默认值
在项目中需要为Ant Design Vue 的 select 组件设置一个默认值,如下图所示的状态下拉选择框,默认选择全部 代码如下: <a-select v-model="query ...
- Ant Design Vue Pro 项目实战-项目初始化(一)
写在前面 时间真快,转眼又是新的一年.随着前后端技术的不断更新迭代,尤其是前端,在目前前后端分离开发模式这样的一个大环境下,交互性.兼容性等传统的开发模式已经显得有些吃力.之前一直用的是react,随 ...
- 使用ant design vue的日历组件,实现一个简单交易日与非交易日的切换
使用ant design vue的日历组件,实现一个简单交易日与非交易日的切换 需求: 日历区分交易日.非交易日 可以切换面板查看整年交易日信息 可以在手动调整交易日.非交易日 演示实例 序--使用软 ...
- 使用npm安装 Ant Design Vue 时报错—ant-design-vue@latest(sha1-qsf / gCIFcRYxyGmOKgx7TmHf1z4 =)seems to be corrupted.
安装 Ant Design Vue 时报错: npm install ant-design-vue --save ant-design-vue @ latest(sha1-qsf / gCIFcRYx ...
- Vue3学习(二)之集成Ant Design Vue
一.集成Ant Design Vue npm install ant-design-vue@2.0.0-rc.3 --save 兼容性 Ant Design Vue 2.x 支持所有的现代浏览器. 如 ...
- Ant Design Vue项目解析-前言
源码系列文章很长时间没有更新,一是在考虑文章用什么方式写质量会更高,用什么方式总结更易于扩展和总结知识点,加上工作.看书.健身占用的时间比较多所以也没时间去整理.最近在网上看到一篇文章感觉这种方式不错 ...
- jeecg ant design vue 一些收藏
1关于 进来清除上次记录 找到src/permission.js下的
- 文档驱动 —— 表单组件(五):基于Ant Design Vue 的表单控件的demo,再也不需要写代码了。
源码 https://github.com/naturefwvue/nf-vue3-ant 特点 只需要更改meta,既可以切换表单 可以统一修改样式,统一升级,以最小的代价,应对UI的升级.切换,应 ...
- jeecg ant design vue一级菜单跳到外部页面——例如跳到百度
需求:点击首页跳到百度新打开的页面 找到SideMenu.vue 对应的inde.js找到renderMenuItem 函数.加一个判断 if(menu.meta.url=='https://ww ...
随机推荐
- 红米手机 android4.4.4 root之路
第一步: 进入360root官网下载apk安装包: http://root.360.cn/index.html 说明:不是所有的机型都能root, 一般android5.0 以下的系统root的成功 ...
- MySQL的使用方法和视图、索引、以及存储过程的一些简单方法
一,基本概念 1, 常用的两种引擎: (1) InnoDB a,支持ACID,简单地说就是支持事务完整性.一致性: b,支持行锁,以及类似ORACLE的一 ...
- DNS bind使用
概念介绍 DNS的分类 主DNS:配置管理,不提供服务,只用来编辑配置信息,给从DNS提供同步数据 从DNS:从主DNS上同步数据信息,对外提供服务 缓存DNS:在主DNS和从DNS之间,用来递归解析 ...
- 性能测试之JVM的故障分析工具VisualVM
VisualVM 是随JDK一同发布的jvm诊断工具,通过插件可以扩展很多功能,插件扩展也是其精华所在. 提供了一个可视界面,用于在Java应用程序在Java虚拟机上运行时查看有关Java应用程序的详 ...
- Java前端面试题总结
Java前端面试题总结 简单说一下HTML,CSS,javaScript在网页开发中的定位? HTML:超文本标记语言,定义网页的结构 CSS:层叠样式表,用来美化页面 JavaScript:主要用来 ...
- typora中的图片处理20200622
typora中的图片处理20200622 食用建议 typora作为markdown的书写神器,一般习惯的流程是在typora中写完,然后复制粘贴到博客园中,然而,markdown中图片采用的是本地连 ...
- 循序渐进VUE+Element 前端应用开发(13)--- 前端API接口的封装处理
在前面随笔<循序渐进VUE+Element 前端应用开发(12)--- 整合ABP框架的前端登录处理>介绍了一个系统最初接触到的前端登录处理的实现,但往往对整个系统来说,一般会有很多业务对 ...
- 浅谈pyautogui模块
pyautogui模块 PyAutoGUI--让所有GUI都自动化 安装代码: pip install pyautogui 目的 PyAutoGUI是一个纯Python的GUI自动化工具,其目的是可以 ...
- Spring Boot2.x 的Druid连接池配置[附带监控]
父依赖[Spring Boot 2.1.x版本] <parent> <groupId>org.springframework.boot</groupId> < ...
- Netty 源码解析(四): Netty 的 ChannelPipeline
今天是猿灯塔“365篇原创计划”第四篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源码解析(二): Netty 的 Channel Netty ...