折腾了差不多一天.不是从Eleme源码而是另外的角度解决了这个问题:
首先我发现,在append/remove节点之后,结果是会反映在ElTree
(用VueDevTools查看)里的一些属性里的.比如_data.root.childNodes
.所以在Append/Delete方法里动态获取它里面的我们想要的数据(id,label,childNodes).然后赋值给this.data就好了.
所以我就写了一个函数来做这件事:
testFunc(){
//我们想要的数据,在这里面.你可以打印出来研究一下.
let tempObj = this.$refs.treeParent.$children[0]['_data'].root.childNodes;
//在获取数据之前,需要深克隆一下上面的对象,因为后面我们需要直接处理该对象.
// DeepCopy函数来自https://zhuanlan.zhihu.com/p/23251162
function DeepCopy(obj) {
// Hash表 记录所有的对象引用关系
let map = new WeakMap();
function dp(obj) {
let result = null;
let keys = null,
key = null,
temp = null,
existObj = null;
existObj = map.get(obj);
// 如果这个对象已被记录则直接返回
if (existObj) {
return existObj;
}
keys = Object.keys(obj);
result = {};
// 记录当前对象
map.set(obj,result);
for (let i = 0; i < keys.length; i++) {
key = keys[i];
temp = obj[key];
// 如果字段的值也是一个对象则递归复制
if (temp && typeof temp === 'object') {
result[key] = dp(temp);
} else {
// 否则直接赋值给新对象
result[key] = temp;
}
}
return result;
}
return dp(obj);
}
//dealData方法处理对象,把对象变成{"id":123,"label":"test",childNodes:[]}的形式,会删除所有其他属性
function dealData(obj) {
for (let attr of Object.keys(obj)) {
if (attr != "data" && attr != "childNodes") {
delete obj[attr];
}
}
if (obj.hasOwnProperty('data')) {
obj.id = obj.data.id;
obj.label = obj.data.label;
delete obj.data;
}
for (let item in obj.childNodes) {
if(item){
dealData(obj.childNodes[item]);
};
}
}
//在上面DeepCopy时,把childNodes变成了object,但我们想要的是Array.所以本函数可以把它转换回来.
function objToArray(obj) {
let arr = [];
for (let item in obj.childNodes) {
if (item) {
arr.push(obj.childNodes[item]);
}
}
obj.childNodes = arr;
for (let a of arr) {
objToArray(a);
}
}
// data 模拟 this.data
let data = [];
for (const item of Object.values(tempObj)){
let copied = DeepCopy(item);
dealData(copied);
copied = JSON.parse(JSON.stringify(copied));
objToArray(copied);
data.push(copied);
}
// data里的数据是我们想要的.可以直接赋值给this.data来解决Element的这个Bug.
return data;
},
append(store,data) {
store.append({
id: id++,
label: 'test',
children: []
}, data);
let obj = this.testFunc();
this.$set(this,"data",obj);
},
remove(store, data) {
store.remove(data);
let obj = this.testFunc();
this.$set(this,"data",obj);
},