1. 程式人生 > 實用技巧 >vue原始碼分析(二)>>:watch

vue原始碼分析(二)>>:watch

今天來分析一下watch原始碼實現方式,watch就是實現某個屬性發生變化立即得到通知。

step1:watch用法:

  基本用法如下(寫的比較粗糙,看不明白的看這篇基礎點的:https://www.cnblogs.com/rainbowLover/p/13036284.html):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0"
> <title>vue-watch</title> </head> <body> <div id="app"> <p>info.name-{{info.name}}</p> <p>info.age-{{info.age}}</p> <p>hoppy-{{hobby}}</p> <p>tip-{{tip}}</p> <button @click="handleClick">click</
button> </div> <script src="../../dist/vue.min.js"></script> <script> let vm = new Vue({ el:'#app', data:{ info:{ name:'張三', age:22 }, hobby:'love', tip:'哈哈' }, mounted() { // 用Vue的$watch新增,引數一:監聽的屬性名,引數二:回撥,引數三:配置
this.$watch('tip',this.tipChanged,{immediate:true}) }, methods: { handleClick(){ this.info.name = '李四' this.info.age = 66 this.hobby = 'make' this.tip = '呵呵' }, tipChanged(){ console.log("tip watch >>:", arguments); } }, watch: { hobby(){// 方法名就是監聽的屬性名 console.log("hobby watch >>:", arguments); }, 'info.name':function(){// 監聽info的屬性name console.log("info.name watch >>:", arguments); }, info:{// 監聽info immediate:true,// 立馬執行 頁面載入時候會執行一次回撥方法 deep:true,// 開啟深度監聽的話 info的屬性變化也會觸發回撥, handler:function(){// 回撥 console.log("info watch >>:", arguments); } } } }) </script> </body> </html>

step2:watch原始碼實現:

  vue在例項化時候走_init()方法,在beforeCreate和created之間回撥用initState方法,繼續追蹤這個方法:這個方法是初始化資料相關的物件,在這個方法裡邊看到先後執行了:initProps、initMethods、initData、initComputed,最後執行initWatch方法。看看這個方法:

  function initWatch (vm, watch) {
    for (var key in watch) {
      var handler = watch[key];
      if (Array.isArray(handler)) {
        for (var i = 0; i < handler.length; i++) {
          createWatcher(vm, key, handler[i]);
        }
      } else {
        createWatcher(vm, key, handler);
      }
    }
  }

斷點看到watch是:就是介面上定義的watch裡邊的東西

這裡看到watch[key]還可以是陣列?然後我趕緊去試一下:改成這樣

發現hobby變化時候這兩個方法都執行了!然後繼續往下看:createWatcher

// 查詢發現 這個方法只被初始化watch過程呼叫
  // 引數一:vue例項物件
  // 引數二:key
  // 引數三:定義的方法或者深度監聽等配置
  // 引數四:深度監聽等配置 只有this.$watch()方法定義watch時候使用,
  function createWatcher (
    vm,
    expOrFn,
    handler,
    options
  ) {
    // 如果是物件 就是深度監聽那種定義方法 info的那個定義
    if (isPlainObject(handler)) {
      options = handler;
      handler = handler.handler;
    }
    // 如果是字串 就去看看方法裡邊定義的該方法
    if (typeof handler === 'string') {
      handler = vm[handler];
    }
    // 呼叫$watch
    return vm.$watch(expOrFn, handler, options)
  }

通過這個方法,把不同方式定義的watch規範一下,找到回撥方法,然後繼續看$watch方法:

step3:watch觸發: