场景: 地图组件页面中,偶尔间发现marker图标有时能看到, 有时看不到,造成了使用的显示问题,
定位问题: 原来是因为watch里面监听的地图数组集合未被触发,所以没有调用到addMarker函数
发现问题,那就得解决问题,先给大家捋一下解决步骤
逻辑
首先梳理下逻辑,父级页面中,调用地图组件的同时,并发送获取地址的接口。接下来,子组件的地图服务已经被调用了, 渲染了地图,当接口地址数据拿回后,会触发watch事件,调用里面的addMarker方法,显示marker
排查问题
打上了断点,发现是因为watch中监听的父传子变量未触发,这是为啥???
网速快的情况下,先渲染子组件,接口数据后拿回,拿回后传给子组件时,触发了变化,这个没有问题的。
网速慢的情况下,先拿到接口数据,再渲染子组件,这个时候,
尝试一
在父级页面给子组件加个v-if,拿到数据后才能调用组件
- 网速慢的话,子组件是一个地图控件,有背景什么的,接口不知道什么时候才能返回,总不能一直空着;
- 网速快的话,页面正常
尝试二
试着在mounted中先一步调用addMarker
- 网速慢的话,在mounted中已经到了地址数据,调用addMarker, watch未触发,所以不用调用addMarker;
- 网速快的话,在mounted中未拿到地址数据, addMarker被调用了一次(没有数据未渲染marker),拿到数据后,addMarker又被调用了一下(有数据渲染marker),感觉这个也不是特别符合逻辑,(假设在mounted中有数据的话,那就是addMarker被重复调用并渲染了两次)
尝试三
watch中使用immediate: true
- 网速慢的话,会强制调用addMarker,并且调用时有值,但是这个时候,地图控件还没有被创建出来,this.map为空,更别说给他添加marker了,地图使用时是有一个循序渐进的过程,所以又被卡在这里了
- 网速快的话,会强制调用addMarker,但是调用的时候是没有值的,然后有值的时候再调用addMarker,相当于又是两次调用;
尝试四(解决)
使用this.$set(),意思就是说会设置属性值,触发视图更新;
- 网速慢的话,在created中使用$set, 会在数据发生变化时,触发watch,形成跟网速快时一样的操作,
- 网速快的话,页面正常
props: {
gisInfo: {
type: Object,
default: function () {
return {};
}
},
},
data: function () {
return {
gisInfoList: {}
};
},
methods: {
addMarker: function () {
var keys = Object.keys(this.gisInfoList);
if (keys.length) {
// 执行内容
}
}
},
created: function () {
this.$set(this.gisInfo); // 初始化设置下 不赋值他就是有个默认的undefined
console.log(this.gisInfo); // {undefined: undefined}
},
watch: {
gisInfo: {
handler: function (val) {
let obj = {};
let keys = Object.keys(val);
if (keys.length) {
keys.forEach(function (key) {
if (key != 'undefined') {
obj[key] = val[key];
}
})
}
this.gisInfoList = obj; // 如果直接赋值给gisInfo,会再次触发watch,陷入循环
this.addMarker();
},
deep: true
},
}
至此,问题解决了,但是个人感觉那个判断undefined的方法不太好,如果大家有好的解决方法,可以推荐下,谢谢
网友评论