美文网首页
父传子未触发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事件

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