vue3的watch用法以及和vue2中watch的區(qū)別
watch介紹
watch 屬性監(jiān)聽(tīng) 是一個(gè)對(duì)象,鍵是需要觀察的屬性,值是對(duì)應(yīng)回調(diào)函數(shù),主要用來(lái)監(jiān)聽(tīng)某些特定數(shù)據(jù)的變化,從而進(jìn)行某些具體的業(yè)務(wù)邏輯操作,監(jiān)聽(tīng)屬性的變化,需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開(kāi)銷(xiāo)較大的操作時(shí)使用。
Vue2 用法
在 Vue2 的 options API 中, watch 與 methods 一樣作為一個(gè)模塊,在其中定義相應(yīng)的監(jiān)聽(tīng)事件
監(jiān)聽(tīng)基礎(chǔ)變量
需要監(jiān)聽(tīng)的普通變量,要在 watch 模塊中,定義 以該變量名命名 的函數(shù),就像下面的 count
<template>
<div>
<h2>{{ count }}</h2>
<button @click="count++">+</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0
}
},
watch: {
// count 接收一個(gè)回調(diào)函數(shù),當(dāng)數(shù)據(jù)變化時(shí)會(huì)執(zhí)行該函數(shù),接收兩個(gè)參數(shù):
// 第一個(gè)參數(shù)是:最新的值 第二個(gè)參數(shù)是:上一次的值
count: function(newValue, oldValue) {
console.log(newValue, oldValue) // 1, 0
}
}
};
</script>監(jiān)聽(tīng)對(duì)象
需要監(jiān)聽(tīng)的對(duì)象, 在 watch 模塊中定義該變量, 添加 deep 屬性實(shí)現(xiàn)深度監(jiān)聽(tīng)
<template>
<div>
<h2>{{ data.count }}</h2>
<button @click="data.count++">+</button>
</div>
</template>
<script>
export default {
data() {
return {
data: {
count: 0
}
}
},
watch: {
data: {
change(newValue,oldValue) {
console.log(newValue, oldValue) // 1, 0
},
deep: true, // 添加這個(gè)屬性,當(dāng)data里面深層嵌套的數(shù)據(jù)發(fā)生變化時(shí)也可以執(zhí)行回調(diào)
immediate: true // 添加這個(gè)屬性,當(dāng)界面初始化時(shí)會(huì)先執(zhí)行一次
}
}
};
</script>Vue3的用法
Vue3 的 Composition API 中, watch 作為函數(shù)調(diào)用, 在函數(shù)中定義相應(yīng)的事件邏輯
監(jiān)聽(tīng)基礎(chǔ)類(lèi)型
<template>
<div class="card">
<span>{{ count }}</span>
<button @click="Add">+</button>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
const count = ref(0);
watch(count, (newValue, oldValue) => {
console.log('newValue->', newValue);
console.log('oldValue->', oldValue);
})
const Add = () => {
count.value++;
}
</script>
監(jiān)聽(tīng)復(fù)雜類(lèi)型
<template>
<div>
<button @click="change">change</button>
</div>
</template>
<script setup>
import { ref, watch, reactive } from "vue";
const user = reactive({
name: "jake",
phone: "10010",
score: {
math: 90,
english: 80,
},
});
const change = () => {
user.name = "mike";
};
</script>復(fù)雜類(lèi)型的監(jiān)聽(tīng)有很多種情況,具體的內(nèi)容如下
監(jiān)聽(tīng)整個(gè)對(duì)象(使用較多)
// 監(jiān)聽(tīng)整個(gè)對(duì)象;
watch(user, (newValue, oldValue) => {
console.log("newValue->", newValue);
console.log("oldValue->", oldValue);
});其第一個(gè)參數(shù)是直接傳入要監(jiān)聽(tīng)的對(duì)象 user。當(dāng)監(jiān)聽(tīng)整個(gè)對(duì)象時(shí),只要這個(gè)對(duì)象有任何修改,那么就會(huì)觸發(fā) watch 方法。無(wú)論是其子屬性變更(如 user.name),還是孫屬性變更(如 user.score.math)...,都是會(huì)觸發(fā) watch 方法。默認(rèn)開(kāi)啟深度監(jiān)聽(tīng),且通過(guò)配置deep:false,無(wú)法關(guān)閉
注意:使用 reactive 定義的數(shù)據(jù)(對(duì)象),無(wú)法獲取正確的oldValue(上一次的值),打印結(jié)果都是一樣

監(jiān)聽(tīng)對(duì)象中的某個(gè)屬性
// 監(jiān)聽(tīng)對(duì)象單個(gè)屬性
watch(
() => user.name,
(newValue, oldValue) => {
console.log("newValue->", newValue);
console.log("oldValue->", oldValue);
}
);如上代碼,監(jiān)聽(tīng) user 對(duì)象的 name 屬性,那么只有當(dāng) user 對(duì)象的 name 屬性發(fā)生變更時(shí),才會(huì)觸發(fā) watch 方法,其他屬性變更不會(huì)觸發(fā) watch 方法。注意,此時(shí)的第一個(gè)參數(shù)是一個(gè)箭頭函數(shù)。
注意:這種方式可以 獲取正確的oldValue(上一次的值),注意和上面的區(qū)分

監(jiān)聽(tīng)對(duì)象 子屬性
// 監(jiān)聽(tīng)對(duì)象子屬性
watch(
() => ({ ...user }),
(newValue, oldValue) => {
console.log("newValue->", newValue);
console.log("oldValue->", oldValue);
}
);這種情況,只有當(dāng) user 的子屬性(name、phone)發(fā)生變更時(shí)才會(huì)觸發(fā) watch 方法。孫屬性,曾孫屬性... 發(fā)生變更都不會(huì)觸發(fā) watch 方法。也就是說(shuō),當(dāng)你修改 user.score.math 或者 user.score.english 時(shí)是不會(huì)觸發(fā) watch 方法的。
注意:這種方式可以 獲取正確的oldValue(上一次的值),但是和上面有略微差別

監(jiān)聽(tīng)對(duì)象所有屬性
// 監(jiān)聽(tīng)整個(gè)對(duì)象,使用 deep 屬性
watch(
() => user,
(newValue, oldValue) => {
console.log("newValue->", newValue);
console.log("oldValue->", oldValue);
},
{ deep: true }
);這個(gè)相當(dāng)于監(jiān)聽(tīng)整個(gè)對(duì)象(效果與上面的第一種相同)。但是實(shí)現(xiàn)方式與上面第一種是不一樣的,這里我們可以看到,第一個(gè)參數(shù)是箭頭函數(shù),并且還多了第三個(gè)參數(shù) { deep: true }。當(dāng)加上了第三個(gè)參數(shù) { deep: true },那么就不僅僅是監(jiān)聽(tīng)對(duì)象的子屬性了,它還會(huì)監(jiān)聽(tīng) 孫屬性,曾孫屬性 ...
注意:這里和第一種情況一樣,無(wú)法獲取正確的oldValue(上一次的值),打印結(jié)果都是一樣

通常要實(shí)現(xiàn)監(jiān)聽(tīng)對(duì)象的所有屬性,都會(huì)采用第一種方法,原因是第一種編碼簡(jiǎn)單,第一個(gè)參數(shù)直接傳入 對(duì)象 即可,雖然 獲取不到 oldValue,但是問(wèn)題不大。
組合監(jiān)聽(tīng)
組合監(jiān)聽(tīng)就是,如果要同時(shí)監(jiān)聽(tīng) user 對(duì)象的 name 屬性,和基礎(chǔ)類(lèi)型 count,只要他們其中任何一個(gè)發(fā)生變更,那么就觸發(fā) watch 方法。
特定情況下要用到
const count = ref(0);
const user = reactive({
name: "jake",
phone: "10010",
score: {
math: 90,
english: 80,
},
});// 組合監(jiān)聽(tīng)
watch([() => user.name, count], ([newName, newCount], [oldName, oldCount]) => {
console.log("newName->", newName);
console.log("oldName->", oldName);
console.log("newCount->", newCount);
console.log("oldCount->", oldCount);
});注意,此時(shí)的第一個(gè)參數(shù)是一個(gè)數(shù)組, 且第二參數(shù)箭頭函數(shù)的參數(shù)也是數(shù)組的形式。

Vue 2 Vue3 小區(qū)別
在 Vue2 的 options API 中, watch 與 methods 一樣作為一個(gè)模塊,如果要監(jiān)聽(tīng)多個(gè)變量,要在其中一個(gè)一個(gè)定義相應(yīng)的監(jiān)聽(tīng)事件
VUE3 的 Composition API可以多次使用 watch 方法,通過(guò)多個(gè)watch 方法來(lái)監(jiān)聽(tīng)多個(gè)對(duì)象。
- Vue2
watch: {
count () {
// 邏輯代碼
},
user: {
name() {
// 邏輯代碼
}
}
}- Vue3
watch(count, () => {})
watch(() => user.name, () => {})computed和watch的區(qū)別
通俗來(lái)講,既能用 computed 實(shí)現(xiàn)又可以用 watch 監(jiān)聽(tīng)來(lái)實(shí)現(xiàn)的功能,推薦用 computed, 重點(diǎn)在于 computed 的緩存功能 ,computed 計(jì)算屬性是用來(lái)聲明式的描述一個(gè)值依賴(lài)了其它的值,當(dāng)所依賴(lài)的值或者變量 改變時(shí),計(jì)算屬性也會(huì)跟著改變; watch 監(jiān)聽(tīng)的是已經(jīng)在 data 中定義的變量,當(dāng)該變量變化時(shí),會(huì)觸發(fā) watch 中的方法。
watch
watch 屬性監(jiān)聽(tīng) 是一個(gè)對(duì)象,鍵是需要觀察的屬性,值是對(duì)應(yīng)回調(diào)函數(shù),主要用來(lái)監(jiān)聽(tīng)某些特定數(shù)據(jù)的變化,從而進(jìn)行某些具體的業(yè)務(wù)邏輯操作,監(jiān)聽(tīng)屬性的變化,需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開(kāi)銷(xiāo)較大的操作時(shí)使用
computed
computed 計(jì)算屬性 屬性的結(jié)果會(huì)被緩存,當(dāng) computed 中的函數(shù)所依賴(lài)的屬性沒(méi)有發(fā)生改變的時(shí)候,那么調(diào)用當(dāng)前函數(shù)的時(shí)候結(jié)果會(huì)從緩存中讀取。除非依賴(lài)的響應(yīng)式屬性變化時(shí)才會(huì)重新計(jì)算,主要當(dāng)做屬性來(lái)使用 computed 中的函數(shù)必須用 return 返回最終的結(jié)果, computed 更高效,優(yōu)先使用。data 不改變,computed 不更新。
適用場(chǎng)景
computed:當(dāng)一個(gè)屬性受多個(gè)屬性影響的時(shí)候使用,例:購(gòu)物車(chē)商品結(jié)算功能watch: 當(dāng)一條數(shù)據(jù)影響多條數(shù)據(jù)的時(shí)候使用,例:搜索數(shù)據(jù)
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 前端面試之vue2和vue3的區(qū)別有哪些
- vue2.x,vue3.x使用provide/inject注入的區(qū)別說(shuō)明
- Vue2和Vue3在v-for遍歷時(shí)ref獲取dom節(jié)點(diǎn)的區(qū)別及說(shuō)明
- 由淺入深講解vue2和vue3的區(qū)別
- vue2與vue3中生命周期執(zhí)行順序的區(qū)別說(shuō)明
- vue2與vue3雙向數(shù)據(jù)綁定的區(qū)別說(shuō)明
- Vue2與Vue3兄弟組件通訊bus的區(qū)別及用法
- Vue2.x與Vue3.x中路由鉤子的區(qū)別詳解
- 稍微學(xué)一下Vue的數(shù)據(jù)響應(yīng)式(Vue2及Vue3區(qū)別)
- Vue2.X和Vue3.0數(shù)據(jù)響應(yīng)原理變化的區(qū)別
- 深入淺出分析vue2和vue3的區(qū)別
相關(guān)文章
關(guān)于Element-UI中slot的用法及說(shuō)明
這篇文章主要介紹了關(guān)于Element-UI中slot的用法及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
Vite項(xiàng)目搭建與環(huán)境配置的完整版教程
Vite?使用?Rollup?作為默認(rèn)的構(gòu)建工具,可以將應(yīng)用程序的源代碼打包成一個(gè)或多個(gè)優(yōu)化的靜態(tài)文件,本文就來(lái)為大家介紹一下Vite如何進(jìn)行項(xiàng)目搭建與環(huán)境配置吧2023-09-09
vue3.0 vue-router4.0打包后頁(yè)面空白的解決方法
本文主要介紹了vue3.0 vue-router4.0打包后頁(yè)面空白的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
解決vue創(chuàng)建項(xiàng)目使用vue-router和vuex報(bào)錯(cuò)Object(...)is not a&nb
這篇文章主要介紹了解決vue創(chuàng)建項(xiàng)目使用vue-router和vuex報(bào)錯(cuò)Object(...)is not a function問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
vue項(xiàng)目使用node連接數(shù)據(jù)庫(kù)的方法(前后端分離)
這篇文章主要介紹了vue項(xiàng)目使用node連接數(shù)據(jù)庫(kù)(前后端分離),本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
Vue實(shí)現(xiàn)商品分類(lèi)菜單數(shù)量提示功能
這篇文章主要介紹了Vue實(shí)戰(zhàn)—商品分類(lèi)菜單數(shù)量提示功能,本文通過(guò)項(xiàng)目實(shí)戰(zhàn)給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07
vue不用window的方式如何刷新當(dāng)前頁(yè)面
這篇文章主要介紹了vue不用window的方式如何刷新當(dāng)前頁(yè)面,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
如何解決ECharts圖表切換后縮成一團(tuán)的問(wèn)題
這篇文章主要介紹了如何解決ECharts圖表切換后縮成一團(tuán)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10

