美文网首页
父传子未触发watch事件

父传子未触发watch事件

作者: 成神之路_be73 | 来源:发表于2020-09-02 15:23 被阅读0次

场景: 地图组件页面中,偶尔间发现marker图标有时能看到, 有时看不到,造成了使用的显示问题,
定位问题: 原来是因为watch里面监听的地图数组集合未被触发,所以没有调用到addMarker函数
发现问题,那就得解决问题,先给大家捋一下解决步骤

逻辑
首先梳理下逻辑,父级页面中,调用地图组件的同时,并发送获取地址的接口。接下来,子组件的地图服务已经被调用了, 渲染了地图,当接口地址数据拿回后,会触发watch事件,调用里面的addMarker方法,显示marker

排查问题
打上了断点,发现是因为watch中监听的父传子变量未触发,这是为啥???
网速快的情况下,先渲染子组件,接口数据后拿回,拿回后传给子组件时,触发了变化,这个没有问题的。
网速慢的情况下,先拿到接口数据,再渲染子组件,这个时候,\color{red}{ 虽然我props中默认为空,并且父传子的数据是有值的,但是还是没有触发变化,所以没有调用addMarker事件}

尝试一
在父级页面给子组件加个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的方法不太好,如果大家有好的解决方法,可以推荐下,谢谢

相关文章

  • 父传子未触发watch事件

    场景: 地图组件页面中,偶尔间发现marker图标有时能看到, 有时看不到,造成了使用的显示问题,定位问题: 原来...

  • vue组件如何通信

    父传子:props; 子传父:this.$emit 自定义事件:event.emit触发 event.$off...

  • vue组件传值

    父传子 通过props传递 子传父 在父组件中给子组件绑定一个自定义的事件,子组件通过$emit()触发该事件并传...

  • 状态管理Bus的使用

    Bus 1. 父子组件之间通信 父传子 props 子传父 $emit 事件触发 2. 兄弟之间传值 同一父组件兄...

  • 组件间传值

    父子组件传值父传子 // 接收父组件传值 子传父 // 触发一个自定义事件 祖孙组件传值// 添加依赖数据,它里面...

  • 微信小程序父子组件传值

    子传父:事件传递 父传子:属性传递

  • vuex

    vue中数据通信的方式1.父传子, 通过属性传递。2.子传父, 子父通信是通过emit来触发父级事件。 3.跨组件...

  • React事件传递

    事件传递: 父传子、子传父; 父传子 简单实例: 子传父 简单实例: 同级组件传值 简单实例: 方法一: 通过父...

  • vue面试常见问题

    vue中动态绑定class的方式? watch和computed的区别 vue中key的作用 vue父传子 子传父...

  • 2018-01-09(可视化构建工具bug修复)

    组件传参 父传子 父组件 子组件 子传父子组件 父组件 watch的使用 模拟器移除问题的解决 使用JavaScr...

网友评论

      本文标题:父传子未触发watch事件

      本文链接:https://www.haomeiwen.com/subject/pqvzjktx.html