computed
与 watch
深度解析在 Vue 3 组合中,响应式工具的类型安全使用至关重要。以下是详细说明
watch
侦听器<template>
<div>实际参数1={{count}}div>
<div>
<button @click="count++">点击button>
div>
template>
<script setup lang="ts">
import {
reactive,
ref,
watch
} from "vue";
const count = ref<number>(0)
const state = reactive({items: [] as string[]});
watch(count, (newVal:number, oldVal:number) => {
state.items.push(String(count.value))
console.log('newVal, oldVal === ', newVal, oldVal)
})
watch(() => state.items, () => {
console.log('state.items ===', state.items)
},{deep: true})
script>
<template>
<div>实际参数1={{count}}div>
<div>
<button @click="count++">点击button>
div>
template>
<script setup lang="ts">
import {
reactive,
ref,
watch
} from "vue";
const count = ref<number>(0)
const state = reactive({items: [] as string[]});
watch(count, (newVal:number, oldVal:number) => {
state.items.push(String(count.value))
console.log('newVal, oldVal === ', newVal, oldVal)
})
watch(() => state.items, () => {
console.log('state.items ===', state.items)
},{deep: true})
watch([count, state], ([newCount, newState]:[number, object], [oldCount, oldState]:[number, object])=> {
console.log('[newCount, newState], [oldCount, oldState] =', newCount, newState, oldCount, oldState)
})
script>
<template>
<div>实际参数1={{product}}div>
<div>
<button @click="product.price++">点击button>
div>
template>
<script setup lang="ts">
import {
reactive,
watch
} from "vue";
interface Product {
id: number,
price: number,
name: string,
specs: {
color: string,
weight: number
}
}
const product = reactive<Product>({
id: 1,
price: 131,
name: 'Bwm',
specs: {
color: 'red',
weight: 80
}
})
watch(() => product.price, // 创建新引用触发深度监听
(newProduct,oldProduct) => {
console.log('newVal,oldVal === ', newProduct,oldProduct)
},{deep: true})
script>
watchEffect
高级用法watchEffect() 允许我们自动跟踪回调的响应式依赖,且会立即执行。
<template>
<div>实际参数1={{product}}div>
<div>
<button @click="product.price++">点击button>
div>
template>
<script setup lang="ts">
import {
reactive,
ref,
watch, watchEffect
} from "vue";
interface Product {
id: number,
price: number,
name: string,
specs: {
color: string,
weight: number
}
}
const product = reactive<Product>({
id: 1,
price: 131,
name: 'Bwm',
specs: {
color: 'red',
weight: 80
}
})
const totalPrice = ref<number>(0)
watchEffect(()=> {
totalPrice.value = product.price + 2
console.log('totalPrice === ', totalPrice)
})
script>
<template>
<div>实际参数1={{product}}div>
<div>
<button @click="product.price+=10">点击button>
div>
template>
<script setup lang="ts">
import {
reactive,
ref,
watchEffect,
onWatcherCleanup
} from "vue";
interface Product {
id: number,
price: number,
name: string,
specs: {
color: string,
weight: number
}
}
const product = reactive<Product>({
id: 1,
price: 131,
name: 'Bwm',
specs: {
color: 'red',
weight: 80
}
})
const totalPrice = ref<number>(0)
watchEffect(()=> {
totalPrice.value = product.price + 2
console.log('totalPrice === ', totalPrice)
onWatcherCleanup(() => {
console.log('onWatcherCleanup ===')
})
})
script>
computed
计算属性<template>
<div>实际参数1={{totalPrice}}</div>
<div>
<button @click="product.price+=10">点击</button>
</div>
</template>
<script setup lang="ts">
import {
reactive,
ref,
computed
} from "vue";
interface Product {
id: number,
price: number,
name: string,
specs: {
color: string,
weight: number
}
}
const product = reactive<Product>({
id: 1,
price: 131,
name: 'Bwm',
specs: {
color: 'red',
weight: 80
}
})
const totalPrice = computed<number>(()=>product.price += 10)
</script>
<template>
<div>{{fullName}}div>
<div>姓名: <el-input v-model="fullName"/>div>
template>
<script setup lang="ts">
import {
reactive,
ref,
computed
} from "vue";
const firstName = ref<string>('Jane')
const lastName = ref<string>('Smith')
const fullName = computed<string>({
get() {
return `${firstName.value} ${lastName.value}`
},
set(fullName:string) {
const [newFirstName, newLastName] = fullName.split(' ')
firstName.value = newFirstName
lastName.value = newLastName
}
})
script>
computed
vs watch
vs watchEffect
对比特性 | computed |
watch |
watchEffect |
---|---|---|---|
目的 | 派生值 | 响应变化执行操作 | 自动追踪依赖执行操作 |
返回值 | ref对象 | 停止函数 | 停止函数 |
初始化执行 | 立即计算 | 可配置(immediate) | 立即执行 |
依赖声明 | 自动 | 显式指定 | 自动 |
缓存 | ✅ | ❌ | ❌ |
异步支持 | ❌ | ✅ | ✅ |
清理机制 | ❌ | ✅ | ✅ |
调试钩子 | ❌ | ✅ | ✅ |
适合场景 | 数据转换/格式化 | 精确控制的操作 | 自动追踪依赖的副作用 |
computed
:
watch
:
watchEffect
:
黄金法则:
computed
watch
或 watchEffect
watch
watchEffect
computed
中产生副作用通过合理选择和使用这些 API,可以构建出高效、可维护的 Vue 3 应用程序。