Vue中watch使用

雖然Vue.js爲咱們提供了有用的computed, 但在某些場景下, 仍然仍是須要使用到watch.express

默認狀況下, watch只在被監聽的屬性值發生變化時執行.函數

例如:性能

export default {
  data: () => ({
    dog: ""
  }),
  watch: {
    dog(newVal, oldVal) {
      console.log(`Dog changed: ${newVal}`);
    }
  }
};
複製代碼

如上代碼所示, 只有當dog的值有發生改變時, watch中的dog函數纔會執行.ui

watch options

immediate

可是, 在某些狀況下, 你可能須要在建立組件後當即運行監聽程序. 固然, 你能夠將邏輯遷移至methods中, 而後從watchcreated鉤子函數中分別調用它, 但有沒有更簡單一點的辦法呢?this

你能夠在使用watch時, 使用immediate: true選項, 這樣它就會在組件建立時當即執行.spa

export default {
  data: () => ({
    dog: ""
  }),
  watch: {
    dog: {
      handler(newVal, oldVal) {
        console.log(`Dog changed: ${newVal}`);
      },
      immediate: true
    }
  }
};
複製代碼

deep

watch中還有一個屬性: deep, 默認值爲: false, 便是否須要開啓深度監聽. 例如:prototype

export default {
  data: () => ({
    obj: {
      hello: 'james'
    }
  }),
  watch: {
    obj: {
      handler(newVal, oldVal) {
        console.log(`obj changed: ${newVal}`);
      },
      immediate: true,
      deep: true
    }
  }
};
複製代碼

deep即深刻觀察, 監聽器會層層遍歷, 給對象的全部屬性(及子屬性)添加監聽器. 這樣作無疑會有很大的性能開銷, 修改obj中任何一個屬性都會觸發監聽器中的處理函數.code

若只想監聽obj中的某個屬性, 可使用字符串監聽形式.對象

export default {
  data: () => ({
    obj: {
      hello: 'james'
    }
  }),
  watch: {
    'obj.hello': {
      handler(newVal, oldVal) {
        console.log(`obj changed: ${newVal}`);
      },
      immediate: true,
      deep: false
    }
  }
};
複製代碼

動態添加watch

Vue源代碼中$watch的實現:事件

Vue.prototype.$watch = function ( expOrFn, cb, options ) {
  var vm = this;
  if (isPlainObject(cb)) {
    return createWatcher(vm, expOrFn, cb, options)
  }
  options = options || {};
  options.user = true;
  var watcher = new Watcher(vm, expOrFn, cb, options);
  if (options.immediate) {
    try {
      cb.call(vm, watcher.value);
    } catch (error) {
      handleError(error, vm, ("callback for immediate watcher \"" + (watcher.expression) + "\""));
    }
  }
  return function unwatchFn () {
    watcher.teardown();
  }
};
複製代碼

基於此, 咱們能夠將上面的示例代碼修改成 動態添加watch, 例如:

export default {
  data: () => ({
    obj: {
      hello: 'james'
    }
  }),
  mounted(){
    this.$watch('obj.hello', this.handler, {
      immediate: true,
      deep: false
    })
  },
  methods: {
    handler(newVal, oldVal) {
      console.log(`obj changed: ${newVal}`);
    }
  }
};
複製代碼

Warning:
正常狀況下, 不推薦使用$watch來動態添加watch, 由於你還須要手動註銷watch監聽事件

註銷watch

若使用動態添加watch, 就須要手動註銷了. 從源代碼中, 能夠看出: this.$watch調用後會有一個返回值, 經過調用此返回值, 便可註銷watch.

修改代碼以下:

let unWatch = null
export default {
  data: () => ({
    obj: {
      hello: 'james'
    }
  }),
  mounted(){
    unWatch = this.$watch('obj.hello', this.handler, {
      immediate: true,
      deep: false
    })
  },
  methods: {
    handler(newVal, oldVal) {
      console.log(`obj changed: ${newVal}`);
    }
  },
  beforeMount(){
    unWatch()
    unWatch = null
  }
};
複製代碼
相關文章
相關標籤/搜索