记录⼀次升级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看到是_traver⽅法报错
function _traver (val, en) {
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 (en.has(depId)) {
return
}
en.add(depId);
}
if (isA) {
i = val.length;
while (i--) { _traver(val[i], en); }
} el {
高血脂怎么办keys = Object.keys(val);
i = keys.length;
while (i--) { _traver(val[keys[i]], en); }
}
}
该⽅法存在于vue项⽬src/core/obrver/traver.js中,
traver 的逻辑也很简单,它实际上就是对⼀个对象做深层递归遍历,因为遍历过程中就是对⼀个⼦对象的访问,会触发它们的 getter 过程,这样就可以收集到依赖,也就是订阅它们变化的 watcher
下⾯的代码就会触发traver:
watch: {
a: {
deep: true, // deep属性为true是关键
handler(newVal) {
console.log(newVal)
}
化妆品品牌排行榜}
}
在 watcher 执⾏ get 求值的过程中有⼀段逻辑:
get() {
let value = call(vm, vm)
// ...
if (this.deep) {
traver(value)
}
}
在traver中打断点,打印出递归的traver的参数name,发现异常:
如果深度遍历⼀个vnode节点,每⼀个vnode都保存有⽗节点和⼦节点的引⽤,遍历所有的vnode确实会导致栈溢出,但是怎么会遍历到⼀个vnode节点呢?
再看前⾯遍历到的⼀个对象,在ant-design-vue⽂档中查到是渲染rowSelection⽤到的,于是在ant-desing-vue的源码查到了 renderRowSelection⽅法: renderRowSelection: function renderRowSelectio
n(prefixCls, locale) {
......
月份前用什么介词
lectionColumn.title = lectionColumn.title
|| h(SelectionCheckboxAll, {
attrs: {
store: this.store,
locale: locale,
data: data,
getCheckboxPropsByItem: CheckboxPropsByItem,
getRecordKey: RecordKey,
disabled: checkboxAllDisabled,
prefixCls: prefixCls,
lections: rowSelection.lections,
hideDefaultSelections: rowSelection.hideDefaultSelections,
getPopupContainer: atePopupContainerFunc()
},
on: {
'lect': this.handleSelectRow
}
});
......
SelectionCheckboxAll组件的locale属性就包含了emptyText,filterRet等,找到了位置,调试⼀下在renderTable中发现如下代码:
// locale⾄少是⼀个空对象
var locale = _extends({}, contextLocale, this.locale);
if (!locale || !ptyText) {
}加减法练习题
......
var columns = derRowSelection(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版本的问题,对⽐了traver⽅法
function _traver (val: any, en: 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 (en.has(depId)) {
return
}
en.add(depId)
春天的早晨
}
经常脚麻if (isA) {
i = val.length
while (i--) _traver(val[i], en)
} el {
keys = Object.keys(val)
i = keys.length
while (i--) _traver(val[keys[i]], en)
}
}
多了 val instanceof VNode这句判断,问题就解决了。看看vue升级记录:
最终的解决⽅案:升级vue版本到
本⽂结束