事情是这样的,有这样一个列表选项输入模块:
在弹框内,其中选项1,选项2是默认的初始项,默认都是无内容,后续用户可以自行添加选项,不保存关闭弹框后,重新打开弹框重新变成默认只有选项1,选项2的初始状态。
const initOptions = new Array(2).fill({input: ''})
export default {
data() {
return {
optionsList: initOptions
}
},
methods: {
addOption() {
this.optionsList.push(xxx);
},
closePopup() {
this.optionsList = initOptions
}
}
}
这样看起来好像没啥问题,定义一个默认的初始化变量initOptions
, 之后如果需要重置optionsList
,那么直接进行初始化赋值即可。但是兄弟们,因为fill
填充的是引用对象,所以实际情况是:
- 因为两个选项都通过双向数据绑定到了
optionsList
的子项中,两个选项输入内容同步输入,即选项1输入1,选项2也同步展示1; - 添加了选项之后,关闭弹框后,重新打开,还是之前输入内容;
这么神奇的事情也是第一次遇到,于是我模拟了一下数组fill
方法,结果让我哭笑不得:
const list = new Array(2).fill({ a: 1 });
console.log(list[0] === list[1]); // true
破案了,我们分析下上面发生问题的原理:
- 双向绑定实际上是指向了同一个引用对象,所以两个选项的输入是同步绑定的;
- 添加选项的操作,变更实际上也指向了引用对象,用来初始化的
initOptions
对象被污染了。
之前fill
方法用的不多,没想到遇到这么个问题,希望能给看到的读者避坑。