vue項(xiàng)目中的數(shù)據(jù)變化被watch監(jiān)聽并處理
vue數(shù)據(jù)變化被watch監(jiān)聽處理
監(jiān)聽當(dāng)前vue文件數(shù)據(jù)
例如,當(dāng)前的vue文件的data中有如下屬性:
data() {
?? ?return {
?? ? ? ?dialogFormVisible: false,
?? ?}
}要監(jiān)聽dialogFormVisible變量的數(shù)據(jù)變化,則代碼如下:
watch: {
? ? dialogFormVisible: function(newVal, oldVal) {
? ? ? alert(newVal);
? ? ? alert(oldVal);
? ? }
}監(jiān)聽vuex中的數(shù)據(jù)
如果vuex中聲明的數(shù)據(jù)如下:
export default new Vuex.Store({
? state: {
? ? avatar: "",?
? },
? mutations: {},
? actions: {},
? modules: {}
});則監(jiān)聽的代碼如下:
watch: {
? ? "$store.state.avatar": function(newValue, oldValue) {
? ? ? ...
? ? }
? },如何正確使用watch監(jiān)聽屬性變化
Vue中可以使用監(jiān)聽器監(jiān)聽屬性的變化,并根據(jù)屬性變化作出響應(yīng)。但一旦涉及到復(fù)雜數(shù)據(jù)的監(jiān)聽(如Object,但數(shù)組一般不需要,因?yàn)閂ue針對(duì)數(shù)組做了特殊處理)時(shí)就比較復(fù)雜了,本文解釋了使用watch監(jiān)聽屬性變化的方法,包括復(fù)雜數(shù)據(jù)。
基本用法
Vue watch最重要的使用場(chǎng)景是根據(jù)某屬性的變化執(zhí)行某些業(yè)務(wù)邏輯:
<template> ? <input type="number" v-model.number="counter" /> </template>
<script>
export default {
? name: "Counter",
? data: function() {
? ? return {
? ? ? counter: 0,
? ? };
? },
? watch: {
? ? counter: function(newV, oldV) {
? ? ? console.log('counter change to %d from %d', newV, oldV);
? ? },
? }
};
</script>watch的基本用法很簡(jiǎn)單:針對(duì)需要監(jiān)聽的屬性定義個(gè)同名的函數(shù)即可,函數(shù)的第一個(gè)參數(shù)為變化后的值,第二個(gè)參數(shù)為變化前的值。
監(jiān)聽object
首先我們回顧一個(gè)JavaScript中的概念:復(fù)雜數(shù)據(jù)變量。“復(fù)雜”的原因在于變量只是一個(gè)引用,和C++中的指針類似,其保存的不是真實(shí)的數(shù)據(jù),而是數(shù)據(jù)的地址。比如對(duì)于一個(gè)object變量來(lái)說(shuō),添加屬性、刪除屬性、修改屬性的值都不會(huì)改變這個(gè)地址,這也可以說(shuō)這個(gè)object變量沒有變化。不管所用的框架如何,基本定理肯定是生效的,所以Vue中監(jiān)聽object也是一難題,特別是嵌套數(shù)據(jù)的監(jiān)聽。
這里的變化指的是地址的變化,能夠觸發(fā)變化最簡(jiǎn)單的方式就是重新賦值。
<template>
? <div>
? ? <label>up trigger {{ counter.up }} times</label>
? ? <button @click="onTrigger('up')">Trigger Up</button>
? ? <br>
? ? <label>down trigger {{ counter.down }} times</label>
? ? <button @click="onTrigger('down')">Trigger down</button>
? </div>
</template><script>
export default {
? name: "Counter",
? data: function() {
? ? return {
? ? ? counter: {
? ? ? ? up: 0,
? ? ? ? down: 0,
? ? ? },
? ? };
? },
? methods: {
? ? onTrigger: function(type) {
? ? ? this.counter[type] += 1;
? ? }
? },
? watch: {
? ? counter: function(newV, oldV) {
? ? ? // 不會(huì)被觸發(fā)
? ? ? console.log('counter change to %o from %o', newV, oldV);
? ? },
? }
};
</script>針對(duì)counter的監(jiān)聽不會(huì)被觸發(fā),因?yàn)閠his.counter[type] += 1;并不會(huì)使this.counter變化(地址沒變)。那如果想要監(jiān)聽到這個(gè)變化應(yīng)該怎么辦呢?一般來(lái)說(shuō)有兩種方式:
使用deep參數(shù)
watch: {
? counter: {
? ? handler: function(newV, oldV) {
? ? ? console.log('counter change to %o from %o', newV, oldV);
? ? },
? ? deep: true,
? }
}使用deep需要使用watch的完整形式:handler是監(jiān)聽回調(diào)函數(shù),deep: true指定了不僅僅監(jiān)聽counter的變化,也監(jiān)聽其內(nèi)部屬性的變化,所以當(dāng)counter.up或counter.down變化時(shí)才能出發(fā)handler回調(diào)。
重新賦值
methods: {
? onTrigger: function(type) {
? ? // 重新賦值觸發(fā)變化
? ? this.counter = {
? ? ? ...this.counter,
? ? ? [type]: this.counter[type] + 1,
? ? };
? }
},
watch: {
? counter: function(newV, oldV) {
? ? // 不會(huì)被觸發(fā)
? ? console.log('counter change to %o from %o', newV, oldV);
? },
}那兩種方式優(yōu)劣如何呢?使用deep參數(shù)會(huì)為數(shù)據(jù)每一層都添加監(jiān)聽,當(dāng)層級(jí)較深時(shí)比較耗費(fèi)性能,而且Vue不能監(jiān)聽到屬性的添加或刪除。所以一般來(lái)說(shuō)使用重新賦值的方式是較優(yōu)的方案,但如果只是想監(jiān)聽內(nèi)部嵌套數(shù)據(jù)的話,重新賦值就比較重了,所以Vue也提供了直接監(jiān)聽嵌套屬性變化的途徑:
通過(guò)路徑監(jiān)聽內(nèi)部數(shù)據(jù)
watch: {
? 'counter.up': function(newV, oldV) {
? ? console.log('counter.up change to %d from %d', newV, oldV);
? },
? 'counter.down': function(newV, oldV) {
? ? console.log('counter.down change to %d from %d', newV, oldV);
? },
}通過(guò)這種方式可以避免使用deep造成的性能消耗問(wèn)題,當(dāng)只對(duì)某內(nèi)部屬性變化作出響應(yīng)的場(chǎng)景下比較合適,但仍要注意監(jiān)聽的路徑數(shù)據(jù)仍是復(fù)雜數(shù)據(jù)時(shí)的場(chǎng)景。
初始化變量觸發(fā)監(jiān)聽回調(diào)
使用watch監(jiān)聽變化時(shí),給變量初始值不會(huì)觸發(fā)監(jiān)聽函數(shù),如果像要改變這個(gè)默認(rèn)設(shè)定可以使用immediate參數(shù),其用法和deep類似:
watch: {
? counter: {
? ? handler: function(newV, oldV) {
? ? ? console.log('counter change to %o from %o', newV, oldV);
? ? },
? ? immediate: true,
? }
}這樣在賦初值時(shí)就會(huì)觸發(fā)監(jiān)聽函數(shù),其中第一個(gè)參數(shù)為初始值,第二個(gè)參數(shù)為undefined。
總結(jié):使用watch可以監(jiān)聽屬性的變化,且其使用方式也不少,理解每種方式的使用場(chǎng)景能為開發(fā)節(jié)省時(shí)間,優(yōu)化性能。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于Vue3實(shí)現(xiàn)鼠標(biāo)滑動(dòng)和滾輪控制的輪播
在這篇文章主要為大家詳細(xì)介紹了如何一步步地實(shí)現(xiàn)一個(gè)基于?Vue?3?的輪播組件,這個(gè)組件的特點(diǎn)是可以通過(guò)鼠標(biāo)滑動(dòng)和滾輪來(lái)控制輪播圖的切換,感興趣的可以了解下2024-02-02
vue項(xiàng)目的創(chuàng)建的步驟(圖文教程)
本文主要介紹了vue項(xiàng)目的創(chuàng)建的步驟(圖文教程),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
基于Vue實(shí)現(xiàn)HTML轉(zhuǎn)PDF并導(dǎo)出
這篇文章主要為大家介紹了三種方法,可以實(shí)現(xiàn)將HTML頁(yè)面轉(zhuǎn)為PDF并實(shí)現(xiàn)下載。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以學(xué)習(xí)一下2022-04-04
vue3 emit is not a function問(wèn)題及解決
這篇文章主要介紹了vue3 emit is not a function問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-09-09
vue項(xiàng)目引入svg圖標(biāo)的完整步驟
在實(shí)際的項(xiàng)目開發(fā)中,使用svg圖標(biāo)占用內(nèi)存比圖片更小,映入圖片內(nèi)存比較大,同時(shí)也適用于不同屏幕的尺寸,下面這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目引入svg圖標(biāo)的完整步驟,需要的朋友可以參考下2022-10-10
vue 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的全局調(diào)用彈窗案例
這篇文章主要介紹了vue 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的全局調(diào)用彈窗案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
Vue無(wú)法對(duì)iframe進(jìn)行緩存的解決方案
項(xiàng)目采用的若依框架,但系統(tǒng)中會(huì)嵌入大屏、報(bào)表頁(yè)面,是使用iframe來(lái)實(shí)現(xiàn)的,若依框架的菜單管理中提供了緩存功能,是使用keep-alive實(shí)現(xiàn)的,但對(duì)于iframe頁(yè)面并不生效,所以本文介紹了關(guān)于Vue無(wú)法對(duì)iframe進(jìn)行緩存的解決方案記錄,需要的朋友可以參考下2024-12-12
vue-next/runtime-core 源碼閱讀指南詳解
這篇文章主要介紹了vue-next/runtime-core 源碼閱讀指南詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
vue?url跳轉(zhuǎn)解析和參數(shù)編碼介紹
這篇文章主要介紹了vue?url跳轉(zhuǎn)解析和參數(shù)編碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03

