业务场景

在Vue开发过程中,特别是刚上手不久的同学,很容易遇到,父组件异步获取数据传给子组件,但子组件却没有接收到的问题,如下图所示
在这里插入图片描述

主要原因在于,当父组件异步获取数据的同时,可能耗时较长,获取到数据再传给子组件时,子组件已经渲染完毕
在这里插入图片描述

解决方法

父组件异步获取数据:

const data = ref<string>('')
setTimeout(() => {
  data.value = '我是父组件异步获取的数据'
}, 2000)

传给子组件:

 <son :data="data" />

子组件通过defineProps接收,并通过watch监听父组件传过来的值:

const props = defineProps<{
  data: string
}>()

watch(
  () => props.data,  //监听
  () => {
    console.log(`子组件接收父组件传入的数据`, props.data)
  }
)

子组件将值进行渲染:

  <div>{{ props.data }}</div>

最后就成功啦:
在这里插入图片描述
在这里插入图片描述

Vue3 Watch进一步讲解

watch用法

在 Vue 3 的组合式 API 写法, watch 是一个可以接受 3 个参数的函数


watch(
  source, // 必传,要监听的数据源
  callback, // 必传,监听到变化后要执行的回调函数
  options // 可选,一些监听选项
)

基础用法

  watch(data, () => {
      console.log('监听整个 data', data)
    })

也可以监听对象里面的某个值

  watch(
      // 数据源,getter 形式
      () => data.name,
      // 回调函数 callback
      (newValue, oldValue) => {
        console.log('只监听 name 的变化 ', data.name)
        console.log('打印变化前后的值', { oldValue, newValue })
      }
    )

批量监听

  watch(
      [message, index],
      // 回调的入参也变成了数组,每个数组里面的顺序和数据源数组排序一致
      ([newMessage, newIndex], [oldMessage, oldIndex]) => {
        console.log('message 的变化', { newMessage, oldMessage })
        console.log('index 的变化', { newIndex, oldIndex })
      }
    )

watch监听选项

在这里插入图片描述

deep选项:

 // 定义一个响应式数据,注意我是用的 ref 来定义
    const nums = ref<number[]>([])

    // 2s后给这个数组添加项目
    setTimeout(() => {
      nums.value.push(1)

      // 可以打印一下,确保数据确实变化了
      console.log('修改后', nums.value)
    }, 2000)

    // 但是这个 watch 不会按预期执行
    watch(
      nums,
      // 这里的 callback 不会被触发
      () => {
        console.log('触发监听', nums.value)
      },
      // 因为关闭了 deep
      {
        deep: false,
      }

immediate选项:

watch 默认是惰性的,也就是只有当被监听的数据源发生变化时才执行回调

 // 这个时候不会触发 watch 的回调
    const message = ref<string>('')

    // 2s后改变数据
    setTimeout(() => {
      // 来到这里才会触发 watch 的回调
      message.value = 'Hello World!'
    }, 2000)

    watch(message, () => {
      console.log('触发监听', message.value)
    })

watchEffect

如果一个函数里包含了多个需要监听的数据,一个一个数据去监听太麻烦了,在 Vue 3 ,你可以直接使用 watchEffect API 来简化你的操作

 // 单独定义两个数据,后面用来分开改变数值
    const name = ref<string>('Petter');
    const age = ref<number>(18);

    // 定义一个调用这两个数据的函数
    const getUserInfo = (): void => {
      console.log({
        name: name.value,
        age: age.value
      });
    }

    // 2s后改变第一个数据
    setTimeout(() => {
      name.value = 'Tom';
    }, 2000);

    // 4s后改变第二个数据
    setTimeout(() => {
      age.value = 20;
    }, 4000);

    // 直接监听调用函数,在每个数据产生变化的时候,它都会自动执行
    watchEffect(getUserInfo);

watchEffect和 watch 的区别:

  • watch 可以访问侦听状态变化前后的值,而 watchEffect 没有
  • watch 是在属性改变的时候才执行,而watchEffect 则默认会执行一次,然后在属性改变的时候也会执行
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐