现象:
<e-table :data="noRelateAppList" style="width: 100%" v-loading="loading">
<e-table-column label="名称" width="200" show-overflow-tooltip>
<template slot="header" slot-scope="{ row }">
<e-checkbox
v-model="checkAllNoRelate"
:indeterminate="indeterminateNoRelate"
@change="handleCheckAllNoRelateChange"
></e-checkbox
>名称
<div style="display: none">{{ row }}</div>
</template>
<template slot-scope="{ row }">
<e-checkbox v-model="row.checked" @change="noRelateChange"></e-checkbox>
{{ row.name }}
</template>
</e-table-column>
...
</e-table>
<script>
data() {
return {
loading: false,
size: 20,
page: 1,
total: 20,
checkAllNoRelate: false,
indeterminateNoRelate: false,
noRelateAppListChecked: [], // 可选关联应用列表-已选状态
noRelateAppList: [],
}
},
mounted(){
this.getList()
},
methods:{
getList(){
this.noRelateAppList = this.list.map((item, index) => {
item.checked = false
return item
})
}
}
</script>
点击 checkbox 后 ,noRelateAppList 中点击那一项 checked值更新,视图checkbox 未重新渲染,checkbox组件prop未更新。
原因:
export class Observer {
value: any;
dep: Dep;
vmCount: number; // number of vms that have this object as root $data
constructor (value: any) {
this.value = value
this.dep = new Dep()
this.vmCount = 0
def(value, '__ob__', this)
if (Array.isArray(value)) {
if (hasProto) {
protoAugment(value, arrayMethods)
} else {
copyAugment(value, arrayMethods, arrayKeys)
}
this.observeArray(value)
} else {
this.walk(value)
}
}
/**
* Walk through all properties and convert them into
* getter/setters. This method should only be called when
* value type is Object.
*/
walk (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
/**
* Observe a list of Array items.
*/
observeArray (items: Array<any>) {
for (let i = 0, l = items.length; i < l; i++) {
observe(items[i])
}
}
}
function observe (value, asRootData) {
if (!isObject(value) || value instanceof VNode) {
return
}
var ob;
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__;
} else if (
shouldObserve &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {
ob = new Observer(value);
}
if (asRootData && ob) {
ob.vmCount++;
}
return ob
}
数组对象list 被 赋值给数组noRelateAppList ,在observe(item)时,由于 初始化时list中的item已经添加了__ob__属性,所以noRelateAppList item 执行 observe时,不会重新执行 new Observe,所以新添加的属性没有执行 defineReactive 方法,getter setter 没有被劫持,因此vue监听不到checked属性的变化,checkbox组件未更新。
解决方案:
- 使用Vue.$set() 给数组重新赋值
const temp = this.list.map((item, index) => {
item.checked = false
return item
})
this.$set(this.noRelateAppList, temp)
- 深拷贝一个数组对象,将原数组置空,再赋值给原数组
const test12 = _.cloneDeep(this.list)
const temp = test12.map((item, index) => {
item.checked = false
return item
})
this.noRelateAppList = temp
- map时 返回一个新对象
this.noRelateAppList = test.map((item, index) => {
item = {...item}
item.checked = false
return item
})