雖然Vue.js
爲咱們提供了有用的computed
, 但在某些場景下, 仍然仍是須要使用到watch
.express
默認狀況下,
watch
只在被監聽的屬性值發生變化時執行.函數
例如:性能
export default {
data: () => ({
dog: ""
}),
watch: {
dog(newVal, oldVal) {
console.log(`Dog changed: ${newVal}`);
}
}
};
複製代碼
如上代碼所示, 只有當dog
的值有發生改變時, watch
中的dog
函數纔會執行.ui
可是, 在某些狀況下, 你可能須要在建立組件後當即運行監聽程序. 固然, 你能夠將邏輯遷移至methods
中, 而後從watch
和created
鉤子函數中分別調用它, 但有沒有更簡單一點的辦法呢?this
你能夠在使用watch
時, 使用immediate: true
選項, 這樣它就會在組件建立時當即執行.spa
export default {
data: () => ({
dog: ""
}),
watch: {
dog: {
handler(newVal, oldVal) {
console.log(`Dog changed: ${newVal}`);
},
immediate: true
}
}
};
複製代碼
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
}
};
複製代碼