问题描述:由于一次性返回所有的级联数据的话,数据量太大,接口响应时间太久,因此采用了异步加载的方案,看了vant的官方示例代码,照着改了下,很轻松地实现了功能。正当我感叹世界如此美好的时候,测试人员就给我提了个bug,说选择的数据跟页面显示的数据对不上,我马上进行了自测,发现确实存在这个问题。我做的是个房产选择的一个级联选择器,得先选择小区,然后选楼栋,最后选房产,第一次选择的时候是没问题的,但第二次选择就会出现问题了。比如我选了小区1,再选了楼栋1,这时候再返回去选择小区2,然后再选择小区2下的某一楼栋,比如楼栋2,这时候就有问题了,已选择的数据就会变成了小区1,楼栋1,然后页面可选择的房产也变成了楼栋1下的所有房产了,正常的情况应该是已选择的数据是小区2,楼栋2,页面可选择的房产是楼栋2下的所有房产。
我一开始以为是我自己写的代码有问题,检查了好久,查找了好多资料,都没解决这个问题。没办法只能去看van-cascader这个组件的代码了,打开对应的js文件,以下这段代码立马引起了我的注意:
这个options就是我们传进来的级联数据,它深度监听了options的变动,一旦改变就会去调用updateTabs方法,那我每次选择了小区或者楼栋的时候就会去改变options,所以肯定会触发updateTabs方法,如果不出意外的话,问题肯定是在updateTabs方法里,我们来看看它的具体代码:
javascript
function updateTabs() {
var _this2 = this;
if (this.value || this.value === 0) {
var selectedOptions = this.getSelectedOptionsByValue(this.options, this.value);
if (selectedOptions) {
var optionsCursor = this.options;
this.tabs = selectedOptions.map(function (option) {
var tab = {
options: optionsCursor,
selectedOption: option
};
var next = optionsCursor.filter(function (item) {
return item[_this2.valueKey] === option[_this2.valueKey];
});
if (next.length) {
optionsCursor = next[0][_this2.childrenKey];
}
return tab;
});
if (optionsCursor) {
this.tabs.push({
options: optionsCursor,
selectedOption: null
});
}
this.$nextTick(function () {
_this2.activeTab = _this2.tabs.length - 1;
});
return;
}
}
this.tabs = [{
options: this.options,
selectedOption: null
}];
},
问题就出现在这段代码:
一旦options改变就会执行这段代码,然后tabs就会变成上一次所选择的数据了,导致页面也显示了上一次的数据。
我想到的解决方法就是给这个组件再传一个参数,用来表示要不要执行这段代码的一个标志,具体做法如下:
在props增加一个参数:
将updateTabs方法的代码改为下面这段:
javascript
function updateTabs() {
var _this2 = this
if (this.value || this.value === 0) {
var selectedOptions = this.getSelectedOptionsByValue(this.options, this.value)
if (selectedOptions) {
if(this.changeSelect) {
var optionsCursor = this.options
this.tabs = selectedOptions.map(function(option) {
var tab = {
options: optionsCursor,
selectedOption: option
}
var next = optionsCursor.filter(function(item) {
return item[_this2.valueKey] === option[_this2.valueKey]
})
if (next.length) {
optionsCursor = next[0][_this2.childrenKey]
}
return tab
})
if (optionsCursor) {
this.tabs.push({
options: optionsCursor,
selectedOption: null
})
}
}
this.$nextTick(function() {
_this2.activeTab = _this2.tabs.length - 1
})
return
}
}
this.tabs = [
{
options: this.options,
selectedOption: null
}
]
},
然后在使用这个组件的时候记得把changeSelect传进来,在修改options 之前把changeSelect的值改为false,当options改完后使用
javascript
this.$nextTick(() => {
this.changeSelect = true;
})
把changeSelect 改为true。经过测试,用我改造后的代码就不会有显示错误的问题了。
啊,又是美好的一天~~