watch監(jiān)聽機(jī)制剖析

前言

在vue項目中,數(shù)據(jù)和視圖是可以實現(xiàn)雙向綁定的,修改數(shù)據(jù),視圖隨之改變护桦,反之亦然乙濒。在許多業(yè)務(wù)場景中,我們需要針對視圖數(shù)據(jù)的改變做出相應(yīng)的響應(yīng)操作,這個時候就需要用到vue提供的watch監(jiān)聽機(jī)制。

先給出一個簡單的應(yīng)用示例(以下為vue文件)

<template>
  <div id="bestRecommendMainPage">
    <p>
      <label>當(dāng)前板塊:</label>
      <input type="text" v-model="msg">
    </p>
    <button @click="changeName()">更新</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: "精品書樓"
    };
  },
  watch: {
    msg(newValue, oldValue) {
      console.log(`監(jiān)聽到值發(fā)生變化:${newvalue}`);
    }
  },
  methods: {
    changeName() {
      this.msg = this.msg + '-'
    }
  }
};
</script>

執(zhí)行上述代碼我們會發(fā)現(xiàn),不管是手動修改輸入框內(nèi)的值舱沧,還是點擊按鈕代碼修改msg的值,每當(dāng)msg的值被修改偶洋,都會觸發(fā)watch監(jiān)聽熟吏,打印出對應(yīng)的修改后的新值。

immediate屬性

如果細(xì)心會發(fā)現(xiàn),上述中watch中并沒有監(jiān)聽到msg的初始值:精品書樓牵寺。這就涉及到了watch的一個特點即:默認(rèn)情況下在data數(shù)據(jù)初始化的時候是不被監(jiān)聽的悍引,只有當(dāng)后續(xù)值發(fā)生變化時,才能監(jiān)聽到帽氓。

那么如果我們一定要初始化時就被監(jiān)聽到的話趣斤,我們就可以在watch中設(shè)置一個immediate屬性,故名思意就是即刻觸發(fā)監(jiān)聽的意思黎休,這里也需要用到watch監(jiān)聽的完整寫法:

<script>
export default {
  data() {
    return {
      msg: "精品書樓"
    };
  },
  watch: {
    msg: {
      handler(newvalue,oldvalue) {
        console.log(`監(jiān)聽到值發(fā)生變化:${newvalue}`);
      },
      immediate: true, //該屬性是指data數(shù)據(jù)初始化時即對其中數(shù)據(jù)進(jìn)行監(jiān)聽浓领,mounted中對data數(shù)據(jù)的修改不屬于該屬性范圍
      deep: true
    },
  },
};
</script>

上面代碼中的handler方法就是監(jiān)聽到數(shù)據(jù)變化后需要執(zhí)行后續(xù)處理的函數(shù),immediate為true時势腮,就代表在watch里聲明了msg后联贩,就會立即去執(zhí)行其handler里面的方法,常見的一個適用場景就是父組件向子組件傳值時,需要首次傳入就執(zhí)行監(jiān)聽捎拯。第一個示例就是該寫法的簡易寫法泪幌。

deep屬性

了解了immediate屬性后,我們注意到上面代碼中有一個deep屬性玄渗,這個屬性是做什么的呢座菠?這涉及到了watch監(jiān)聽機(jī)制中的一個深度監(jiān)聽問題狸眼,我們知道上面示例中監(jiān)聽的只是一個變量屬性藤树,那么如果我們監(jiān)聽的是一個對象屬性呢?類似下面的示例:

<template>
  <div id="bestRecommendMainPage">
    <p>
      <label>隨機(jī)數(shù)值一:</label>
      <input type="text" v-model="obj.a">
    </p>
    <button @click="changeNum()">漸增數(shù)值</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      obj: { a: 2 }
    };
  },
  watch: {
    obj: {
      handler(newvalue) {
        console.log(`監(jiān)聽到值發(fā)生變化:${newvalue.a}`);
      },
      immediate: true
    }
  },
  methods: {
    changeNum() {
      ++this.obj.a;
    }
  }
};

這個時候不論是更新視圖中的輸入數(shù)據(jù)拓萌,還是直接代碼中更新數(shù)據(jù)obj.a的值岁钓,watch都是監(jiān)聽不到的。受javascript的限制微王,VUE不能檢測到對象屬性的添加和刪除屡限,VUE會在初始化實例時對data內(nèi)的屬性執(zhí)行g(shù)etter/setter轉(zhuǎn)化過程,也就是說必須是data的屬性才能執(zhí)行該轉(zhuǎn)化炕倘,這里只有改變obj的引用才能被監(jiān)聽到钧大,比如在mounted鉤子函數(shù)中為其重新賦值,這樣才會被監(jiān)聽到罩旋。示例如下

mounted() {
    this.obj = { a: 12 };
},

但這樣并不能解決我們的進(jìn)一步需求啊央,如果要監(jiān)聽obj對象中的屬性變化,要怎么實現(xiàn)涨醋?很簡單瓜饥,設(shè)置deep屬性為true即可。示例如下:

watch: {
    obj: {
      handler(newvalue) {
        console.log(`監(jiān)聽到值發(fā)生變化:${newvalue.a}`);
      },
      immediate: true, 
      deep: true
    }
  },

deep屬性所起的作用是這樣的:它會一層層的向下遍歷浴骂,給對象的所有屬性(也可以是二級三級的)添加監(jiān)聽乓土。但這樣也會產(chǎn)生一個問題:性能開銷過大,對象中任意屬性的改變都會觸發(fā)監(jiān)聽里面的handler方法。所以如果只是針對對象中的某個屬性的話趣苏,可以有兩種處理方法:

一狡相、利用computed計算屬性拦键,將要監(jiān)聽的對象屬性生成一個新屬性,繼而監(jiān)聽這個新屬性芬为。
二萄金、優(yōu)化監(jiān)聽方式媚朦,采用字符串形式(與方法一是一個意思)

"obj.a": {
      handler(newvalue) {
        console.log(`監(jiān)聽到值發(fā)生變化(字符串格式):${newvalue}`);
      }
},

這里要注意的一點時,此時的newValue就是obj.a的新值询张,而不是obj的值。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末份氧,一起剝皮案震驚了整個濱河市唯袄,隨后出現(xiàn)的幾起案子蜗帜,更是在濱河造成了極大的恐慌,老刑警劉巖厅缺,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異湘捎,居然都是意外死亡诀豁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門窥妇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舷胜,“玉大人,你說我怎么就攤上這事活翩∨牍牵” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵纱新,是天一觀的道長展氓。 經(jīng)常有香客問我,道長脸爱,這世上最難降的妖魔是什么遇汞? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上空入,老公的妹妹穿的比我還像新娘络它。我一直安慰自己,他們只是感情好歪赢,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布化戳。 她就那樣靜靜地躺著,像睡著了一般埋凯。 火紅的嫁衣襯著肌膚如雪点楼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天白对,我揣著相機(jī)與錄音掠廓,去河邊找鬼。 笑死甩恼,一個胖子當(dāng)著我的面吹牛蟀瞧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播条摸,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼悦污,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了钉蒲?” 一聲冷哼從身側(cè)響起切端,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎子巾,沒想到半個月后帆赢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體小压,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡线梗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了怠益。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仪搔。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蜻牢,靈堂內(nèi)的尸體忽然破棺而出烤咧,到底是詐尸還是另有隱情,我是刑警寧澤抢呆,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布煮嫌,位于F島的核電站,受9級特大地震影響抱虐,放射性物質(zhì)發(fā)生泄漏昌阿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望懦冰。 院中可真熱鬧灶轰,春花似錦笋颤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至清焕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間秸妥,已是汗流浹背沃粗。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留突雪,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓咏删,卻偏偏與公主長得像督函,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子激挪,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354