vue中props传值和v-if一起使用遇到的问题

1,031 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情

前言

今天在调试vue代码的时候发现一个问题,watch监听某个值变化的时候第一次监听不到。业务场景是有一个模块(子组件)需要根据父组件的中的某个值来控制显示和隐藏,并且这个值在子组件中还被watch监听,当这个值变化的时候要调用相应的接口

原始代码(也就是有问题的代码)

代码如下

父组件:

//父组件中的引用
 <Child v-if="isShow" :airportId="isShow" />
//这里的isShow是一个字符串,有值则为true,无值为false

子组件:

 props: {
    airportId: {
      type: String,
      default: ''
    }
  },
  watch: {
    airportId (val) { //这里监听到有值调用相关的接口
      if (val) {
         this.getUavInfo()
      }
    }
  },
  

上述代码块的问题是当isShow变化时可以被监听到,但第一次变化不会被监听到,举个例子: 也就是说当isShow从空字符变成t001时是监听不到的,但从t001变成t002是可以监听到的。

解决办法

  • 第一种,把父组件中的v-if改为v-show即可
  • 第二种,把父组件中的v-if="isShow"去掉,写在子组件最外层的div上

其中的原理

原来的代码之所以有问题是和vue页面的初始化函数有关,这里的初始化函数不是指vue的生命周期,这里指的是vue源码中的initState(vm)函数,如下图

image.png

这里的初始化顺序是:beforeCreate  ->inject -> Props ->  Methods ->  Data -> Computed -> Watch ->provide-> created

跟我上述代码的错误有关系的就是props和watch,从这里可以看到是先初始化props之后才初始化的watch,所以当我把v-if写在父组件中的时候就会出问题的,因为isShow本来是'',当它变成t001的时候才加载子组件,这时候由于props先初始化了,所以子组件接收到的值就是t001,但这时候watch还没有初始化,所以是监听不到的,当再次改变isShow的才会被检测到。

  • 那为什么父组件中的v-if改为v-show没问题呢,这是因为v-show时组件一直存在,那isShow首次变化之前子组件的props和watch都是初始化好的,那当然可以监听到了。
  • 把v-if移到子组件中可以的原理和v-show类似,子组件被引入父组件就已经初始化好了props和watch,这里v-if是在子组件初始化后才生效的,所以当然也可以监听到了

总结

大概就是这么个情况,问题其实不难,最重要的把其中的逻辑搞清楚了。