在Vue 3中,computed和watch都是用于响应式地处理数据变化的工具,但它们有一些重要的异同点。
异同点如下:
1. 计算属性 (Computed):
- 计算属性是基于它们的依赖进行缓存的。只有在依赖发生变化时,计算属性才会重新计算,可以避免不必要的重复计算。
- 计算属性适用于派生出一些新的数据,比如对数据进行过滤、排序、格式化等操作。
- 计算属性可以像普通属性一样使用,而不需要在模板中调用方法。
- 计算属性中的函数必须有return返回值
2. 监听属性 (Watch):
- 监听属性允许我们在数据变化时执行异步操作或复杂的逻辑。
- 监听属性适用于对数据变化做出响应,比如在数据变化时发送请求、处理副作用等。
- 监听属性可以监听一个或多个数据的变化,并在数据变化时执行相应的操作。
- 监听属性中的函数不是必须要用return返回值。
3. 相似之处:
- 计算属性和监听属性都可以依赖于响应式数据。
- 它们都可以用于监测数据的变化,并作出相应的处理。
总的来说,计算属性适用于派生出新的数据,而监听属性适用于在数据变化时执行异步操作或复杂逻辑。
————————————————
使用方法
1. 计算属性 (Computed):
<template>
<view class="out">
<input type="text" v-model="firstName" placeholder="请输入名"/>
<input type="text" v-model="lastName" placeholder="请输入姓"/>
<view>全称:{{fullName}}</view>
<!-- 在模版中使用方法 -->
<!-- <view>全称:{{fullName()}}</view> -->
</view>
</template>
<script setup>
import {ref,computed} from "vue";
const firstName = ref("迈克尔");
const lastName = ref("乔丹");
// fullName新数据
const fullName = computed(()=> {
console.log("计算属性");
return firstName.value +"-"+ lastName.value
})
// 只有一个值,省略return
// const fullName = computed(()=> firstName.value +"-"+ lastName.value)
console.log(fullName.value);
/* //方法
const fullName = function(){
console.log("方法");
return firstName.value +"-"+ lastName.value;
}
*/
</script>
2. 监听属性 (Watch):
<template>
<view class="out">
<input type="text" v-model="firstName" placeholder="请输入名"/>
<input type="text" v-model="lastName" placeholder="请输入姓"/>
<view>全称:{{fullName}}</view>
<p>
Ask a yes/no question:
<input v-model="question" :disabled="loading" />
</p>
<p>{{ answer }}</p>
</view>
</template>
<script setup>
import {ref,watch, watchEffect} from "vue";
const firstName = ref("迈克尔");
const lastName = ref("乔丹");
const fullName = ref("")
/* 监听多个属性
watch([firstName,lastName],([NfirstName,NlastName],[OfirstName,OlastName])=>{
console.log(NfirstName,NlastName);
console.log(OfirstName,OlastName);
})
*/
// 监听单个属性 -- // 可以直接侦听一个 ref
watch(firstName,(newValue,oldValue)=>{
// 逻辑代码
})
watch(lastName,(newValue,oldValue)=>{
})
// 官方例子
watch(question, async (newQuestion, oldQuestion) => {
if (newQuestion.includes('?')) {
loading.value = true
answer.value = 'Thinking...'
try {
const res = await fetch('https://yesno.wtf/api')
answer.value = (await res.json()).answer
} catch (error) {
answer.value = 'Error! Could not reach the API. ' + error
} finally {
loading.value = false
}
}
})
/* watchEffect是监听所有的响应式数据,页面首次加载会执行一次监听,如果某个数据变化了,就会再次执行,性能可能会差,不建议使用这个
watchEffect(()=>{
console.log(firstName.value,lastName.value);
})
*/
</script>
注意,不能直接侦听响应式对象的属性值,例如:
const obj = reactive({ count: 0 })
// 错误,因为 watch() 得到的参数是一个 number
watch(obj.count, (count) => {
console.log(`Count is: ${count}`)
})
这里需要用一个返回该属性的 getter 函数:
// 提供一个 getter 函数
watch(
() => obj.count,
(count) => {
console.log(`Count is: ${count}`)
}
)
一个返回响应式对象的 getter 函数,只有在返回不同的对象时,才会触发回调:
watch(
() => state.someObject,
() => {
// 仅当 state.someObject 被替换时触发
}
)
可以给上面这个例子显式地加上 deep
选项,强制转成深层侦听器:
watch(
() => state.someObject,
(newValue, oldValue) => {
// 注意:`newValue` 此处和 `oldValue` 是相等的
// *除非* state.someObject 被整个替换了
},
{ deep: true }
)
谨慎使用
深度侦听需要遍历被侦听对象中的所有嵌套的属性,当用于大型数据结构时,开销很大。因此请只在必要时才使用它,并且要留意性能。
即时回调的侦听器
watch
默认是懒执行的:仅当数据源变化时,才会执行回调。但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调。举例来说,我们想请求一些初始数据,然后在相关状态更改时重新请求数据。
可以通过传入 immediate: true
选项来强制侦听器的回调立即执行:
watch(
source,
(newValue, oldValue) => {
// 立即执行,且当 `source` 改变时再次执行
},
{ immediate: true }
)
当 `source` 变化时,仅触发一次,使用 {
once: true
}
参考链接:https://blog.csdn.net/qq_18798149/article/details/135302780