vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue3 Watch、Watcheffect、Computed

Vue3中Watch、Watcheffect、Computed的使用和区别解析

作者:狐说狐有理

Watch、Watcheffect、Computed各有优劣,选择使用哪种方法取决于应用场景和需求,watch 适合副作用操作,watchEffect适合简单的自动副作用管理,computed 适合声明式的派生状态计算,本文通过场景分析Vue3中Watch、Watcheffect、Computed的使用和区别,感兴趣的朋友一起看看吧

Vue3–Watch、Watcheffect、Computed的使用和区别

一、watch

1.功能

watch 用于监听响应式数据的变化,并在数据变化时执行特定的回调函数。适合在响应式数据变化时执行异步操作或复杂逻辑。

2.主要特点

3.典型应用场景

import { ref, watch } from 'vue';
const count = ref(0);
watch(count, (newValue, oldValue) => {
  console.log(`依赖值改变${oldValue} -- ${newValue}`);
}, { immediate: true, deep: false });

4.参数介绍

5.基本使用示例(父子组件结合ElementUI)

父组件

<template>
  <div>
    <!-- 使用 ElementUI 的 el-input 组件输入内容 -->
    <el-input v-model="parentInput" placeholder="Enter something"></el-input>
    <!-- 将输入内容传递给子组件 -->
    <ChildComponent :inputValue="parentInput" />
  </div>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
// 创建一个响应式变量 parentInput,用于存储输入内容
const parentInput = ref('');
</script>

子组件

<template>
  <div>
    <!-- 显示父组件传递的输入内容 -->
    <p>父组件输入: {{ inputValue }}</p>
  </div>
</template>
<script setup>
import { watch, toRefs } from 'vue';
// 定义 props 接收父组件传递的数据
const props = defineProps({
  inputValue: String,
});
// 解构 props
const { inputValue } = toRefs(props);
// 监听 inputValue 的变化,并在变化时执行回调
watch(inputValue, (newValue) => {
  console.log(`父组件输入改变: ${newValue}`);
});
</script>

6.常见用法

1. 监听单个响应式数据

import { ref, watch } from 'vue';
const count = ref(0);
watch(count, (newValue, oldValue) => {
  console.log(`count值改变 ${oldValue} -- ${newValue}`);
});

2. 监听多个响应式数据

import { ref, watch } from 'vue';
const count1 = ref(0);
const count2 = ref(0);
watch([count1, count2], ([newCount1, newCount2], [oldCount1, oldCount2]) => {
  console.log(`count1值改变 ${oldCount1} -- ${newCount1}`);
  console.log(`count2值改变 ${oldCount2} -- ${newCount2}`);
});

3. 深度监听对象{ deep: true }

import { ref, watch } from 'vue';
const person = ref({ name: 'John', age: 30 });
watch(person, (newPerson, oldPerson) => {
  console.log(`Person改变 ${oldPerson.name} -- ${newPerson.name}`);
}, { deep: true });

4. 立即执行回调{ immediate: true }

import { ref, watch } from 'vue';
const count = ref(0);
watch(count, (newValue, oldValue) => {
  console.log(`count值改变 ${oldValue} -- ${newValue}`);
}, { immediate: true });

5. 监听 getter 函数

import { ref, watch } from 'vue';
const count = ref(0);
// 使用 watch 监听一个 getter 函数
watch(
  // 第一个参数是一个 getter 函数,该函数返回我们要监听的计算值
  () => count.value + 1,
  // 第二个参数是回调函数,当 getter 函数的返回值发生变化时,该回调函数会被调用
  (newValue, oldValue) => {
    // 打印旧值和新值
    console.log(`Computed值改变 ${oldValue} -- ${newValue}`);
  }
);

二、watchEffect

1.功能

watchEffect 用于自动运行一个副作用函数,并追踪其依赖。任何依赖变化时都会重新运行该函数。适合用来执行副作用,但不需要明确指定依赖。

2.主要特点

3.典型应用场景

import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect(() => {
  console.log(`count: ${count.value}`);
}, { flush: 'pre' });

4.参数介绍

watchEffectflush 选项用于控制副作用函数的触发时机。flush 选项有三种可能的值:

flush: ‘pre’

默认情况下,watchEffect 会在组件更新之前运行副作用函数。这意味着当响应式数据变化时,副作用会在 DOM 更新前执行。

flush: ‘post’

flush 设置为 'post' 可以在组件更新后触发副作用函数。这对于那些需要访问更新后的 DOM 元素的副作用来说很有用。

flush: ‘sync’

flush 设置为 'sync' 可以使副作用同步触发,而不是等到下一个微任务队列。这意味着副作用会立即在响应式数据变化时执行。

import { ref, watchEffect } from 'vue';
const count = ref(0);
// 默认 flush: 'pre'
watchEffect(() => {
  console.log(`count (pre): ${count.value}`);
});
// flush: 'post'
watchEffect(() => {
  console.log(`count (post): ${count.value}`);
}, { flush: 'post' });
// flush: 'sync'
watchEffect(() => {
  console.log(`count (sync): ${count.value}`);
}, { flush: 'sync' });
count.value++;

三个 watchEffect 会在不同的时机记录 count 的值:

5.基本使用示例(父子组件结合ElementUI)

父组件

<template>
  <div>
    <!-- 使用 ElementUI 的 el-slider 组件输入数值 -->
    <el-slider v-model="sliderValue"></el-slider>
    <!-- 将滑动条的值传递给子组件 -->
    <ChildComponent :sliderValue="sliderValue" />
  </div>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
// 创建一个响应式变量 sliderValue,用于存储滑动条的值
const sliderValue = ref(50);
</script>

子组件

<template>
  <div>
    <!-- 显示父组件传递的滑动条的值 -->
    <p>Slider value: {{ sliderValue }}</p>
  </div>
</template>
<script setup>
import { watchEffect, toRefs } from 'vue';
// 定义 props 接收父组件传递的数据
const props = defineProps({
  sliderValue: Number,
});
// 解构 props
const { sliderValue } = toRefs(props);
// 监听 sliderValue 的变化,并在变化时执行副作用函数
watchEffect(() => {
  console.log(`Slider: ${sliderValue.value}`);
});
</script>

6.常见用法

1. 基本用法

import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect(() => {
  console.log(`count: ${count.value}`);
});

2. 取消副作用

import { ref, watchEffect } from 'vue';
const count = ref(0);
const stop = watchEffect(() => {
  console.log(`count: ${count.value}`);
});
// 停止副作用
stop();

3. 延迟执行{ flush: ‘post’ }

import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect(() => {
  console.log(`count: ${count.value}`);
}, { flush: 'post' });

4. 自定义调度

import { ref, watchEffect } from 'vue';
const count = ref(0);
// 使用 watchEffect 自动追踪副作用
watchEffect(
  () => {
    // 这个函数在 count 发生变化时会被调用
    console.log(`count: ${count.value}`);
  },
  {
    // 配置项:onTrack 和 onTrigger 是调试钩子
    // onTrack 会在副作用追踪依赖时调用
    onTrack(e) {
      console.log('tracked', e);
    },
    // onTrigger 会在依赖变化导致副作用重新执行时调用
    onTrigger(e) {
      console.log('triggered', e);
    }
  }
);

三、computed

1.功能

computed 用于声明计算属性,计算属性会根据其依赖的响应式数据自动更新,并且具有缓存特性。适合计算派生状态或数据。

2.主要特点

3.典型应用场景

import { ref, computed } from 'vue';
const count = ref(0);
const doubleCount = computed(() => count.value * 2);

4.参数介绍

5.基本使用示例(父子组件结合ElementUI)

父组件

<template>
  <div>
    <!-- 使用 ElementUI 的 el-input 组件输入数值 -->
    <el-input v-model="inputValue" placeholder="Enter a number"></el-input>
    <!-- 将输入的数值传递给子组件 -->
    <ChildComponent :number="inputValue" />
  </div>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
// 创建一个响应式变量 inputValue,用于存储输入的数值
const inputValue = ref(0);
</script>

子组件

<template>
  <div>
    <!-- 显示父组件传递的数值的平方 -->
    <p>Squared value: {{ squaredNumber }}</p>
  </div>
</template>
<script setup>
import { computed, toRefs } from 'vue';
// 定义 props 接收父组件传递的数据
const props = defineProps({
  number: Number,
});
// 解构 props
const { number } = toRefs(props);
// 创建一个计算属性 squaredNumber,计算 number 的平方
const squaredNumber = computed(() => number.value * number.value);
</script>

6.常见用法

1. 基本用法

import { ref, computed } from 'vue';
const count = ref(0);
const doubleCount = computed(() => count.value * 2);

2. 可写计算属性 (get set)

import { ref, computed } from 'vue';
const firstName = ref('John');
const lastName = ref('Doe');
const fullName = computed({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (newValue) => {
    const names = newValue.split(' ');
    firstName.value = names[0];
    lastName.value = names[1];
  },
});

3. 依赖其他计算属性

import { ref, computed } from 'vue';
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
const tripleCount = computed(() => doubleCount.value * 1.5);

4. 使用在模板中

<template>
  <div>{{ doubleCount }}</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
</script>

5. 配合 watch 使用

import { ref, computed, watch } from 'vue';
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
watch(doubleCount, (newValue) => {
  console.log(`doubleCount: ${newValue}`);
});

6. 配合 watchEffect 使用

import { ref, computed, watchEffect } from 'vue';
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
watchEffect(() => {
  console.log(`doubleCount: ${doubleCount.value}`);
});

四、总结与区别

watch 的多种用法

watchEffect 的多种用法

computed 的多种用法

区别

特性watchwatchEffectcomputed
功能监听响应式数据变化并执行回调自动运行副作用函数并追踪依赖声明计算属性,根据依赖自动更新并缓存
依赖管理手动指定自动追踪自动管理
缓存
适用场景异步操作、复杂副作用、深度监听界面更新、副作用函数派生状态、数据计算
优点精确控制、支持异步操作自动依赖追踪、代码简洁声明式、自动更新、缓存
缺点需要手动指定依赖、代码相对复杂每次依赖变化时都会重新执行副作用函数需要在创建时指定依赖,无法动态改变计算逻辑

Watch、Watcheffect、Computed三种方法各有优劣,选择使用哪种方法主要取决于具体的应用场景和需求。watch 适合复杂的副作用操作,watchEffect 适合简单的自动副作用管理,而 computed 适合声明式的派生状态计算。

到此这篇关于Vue3中Watch、Watcheffect、Computed的使用和区别解析的文章就介绍到这了,更多相关Vue3--Watch、Watcheffect、Computed内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文