Vue 3 中,watch 和 watchEffect 的区别

结论先行: 

watch 和 watchEffect 都是监听器,都是用来监听响应式数据的变化并执行相应操作。区别是: 

watch:需要指明要监听的数据,而且在回调函数中可以获取到属性变化的前后值;

适用于需要精确控制监视范围的情况;也就是需要针对特定数据变化执行操作。

watchEffect:不用指明监听哪个属性,回调中用到哪个响应式数据,那就监听哪个。

适用于不需要明确定义监视的数据,只需在回调函数内部使用响应式数据并执行相应操作的场景。也就是只需根据数据变化自动追踪的操作。

watchEffect 有点像计算属性 computed:但计算属性必须要写返回值,而 watchEffect 更注重的是过程(回调函数的函数体),所以不用写返回值。

而且,computed 若是值没有被使用时不会调用,但是 watchEffect 始终会调用一次。

具体解析: 

watch 和 watchEffect 都是监听器(侦听器)。用来监听响应式数据的变化并执行相应操作

1、watch  

  • 用于对特定的响应式数据进行监视,并在数据变化时执行相应的操作。
  • 需要显式地指定要监视的数据,并提供回调函数来响应数据变化。
  • 除了监视简单的数据变化外,还可以处理更复杂的监视需求,如监听嵌套对象或数组的变化,并执行相应的操作。
  • 具有一定的惰性。第一次页面展示的时候不会执行,只有数据变化的时候才会执行(设置immediate: true 时可以变为非惰性,页面首次加载就会执行)

它接受3个参数:

  • 一个响应式引用 ref 或一个返回值的 getter 函数
  • 一个回调
  • 可选的配置选项
① watch 侦听单个数据源 
import { ref, watch } from 'vue'

const counter = ref(0)
watch(counter, (newValue, oldValue) => {
  console.log('The new counter value is: ' + counter.value)
})

应用到实际例子中:

// src/components/UserRepositories.vue `setup` function
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted, watch, toRefs } from 'vue'

export default {
  components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
  props: {
    user: {
      type: String,
      required: true
    }
  },
  // 在我们组件中
  setup (props) {
     // 使用 `toRefs` 创建对prop的 `user` property 的响应式引用
    const { user } = toRefs(props)

    const repositories = ref([])
    const getUserRepositories = async () => {
      // 更新 `prop.user` 到 `user.value` 访问引用值
      repositories.value = await fetchUserRepositories(user.value)
    }

    onMounted(getUserRepositories)

    // 在用户 prop 的响应式引用上设置一个侦听器
    watch(user, getUserRepositories)

    return {
      repositories,
      getUserRepositories
    }
 }
},

在我们的 setup 的顶部使用了 toRefs。这是为了确保我们的侦听器能够对 user prop 所做的更改做出反应

② watch 侦听多个数据源

第一个参数以数组形式传入,第二个参数回调返回的结果也是数组

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
  /* ... */
})

Vue3 中监听 reactive 中的值,必须以 getter 函数 的形式,不然会报错。和 Vue2 的区别是不用写 deep 属性,默认就是深度监听了。 

    watch([result2, () => data.title], (newV, oldV) => {
      console.log(newV, oldV) //  [20, "111"] [20, "222"]
    })

 监听 reactive 中的多个值时: 

    watch([result2, () => [data.title, data.value1]], (newV, oldV) => {
      console.log(newV, oldV)
    })

2、watchEffect

立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数。

  • 用于创建一个自动追踪其依赖,并在依赖变化时自动运行的响应式副作用
  • 不需要显式地指定要监视的数据,而是根据回调函数内部使用到的响应式数据自动建立依赖关系。
  • 适用于无需明确定义监视的数据,只需在回调函数内部使用响应式数据并执行相应操作的场景。
  • 立即执行,没有惰性,页面的首次加载就会执行

  • 无法获取到原值,只能得到变化后的值

<template>
  <div>
    <h1>watchEffect - 侦听器</h1>
    <p>{
   
   {data.count}}</p>
    <button @click="stop">手动关闭侦听器</button>
  </div>
</template>

<script>
import { reactive, watchEffect } from "vue";
export default {
  name: "WatchEffect",
  setup() {
    const data = reactive({ count: 1 });
    const stop = watchEffect(() => console.log(`侦听器:${data.count}`));
    setInterval(() => {
      data.count++;
    }, 1000);
    return { data, stop };
  }
};
</script>

 结果:

3、总结  

watch:既要指明要监听的属性,也要指明回调。

watchEffect:不用指明监听哪个属性,回调中用到哪个属性,那就监听哪个属性。

watchEffect 有点像计算属性 computed:

但 computed 注重的计算出来的值(回调函数的返回值),所以必须要写返回值。

而 watchEffect 更注重的是过程(回调函数的函数体),所以不用写返回值。

与 watchEffect 比较,watch 允许我们:

  • 懒执行副作用;
  • 更具体地说明什么状态应该触发侦听器重新运行;
  • 访问侦听状态变化前后的值。

猜你喜欢

转载自blog.csdn.net/qq_38290251/article/details/134271782
今日推荐