To understand the implementation process of Watch, let’s take a look at several ways of using watch
An object whose key is the expression to observe and whose value is the corresponding callback function. The value can also be a method name, or an object that contains options. The Vue instance will call $watch() at instantiation time, iterating through each property of the Watch object.
var vm = new Vue({
data: {
a: 1.b: 2.c: 3.d: 4.e: { f: { g: 5}}},watch: {
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
},
/ / the method name
b: 'someMethod'.// This callback is called whenever the property of any object being listened on changes, no matter how deeply nested it is
c: {
handler: function (val, oldVal) { / *... * / },
deep: true
},
// This callback will be invoked immediately after the listening starts
d: {
handler: 'someMethod'.immediate: true
},
// You can pass in an array of callbacks, which will be called one by one
e: [
'handle1'.function handle2 (val, oldVal) { / *... * / },
{ handler: function handle3 (val, oldVal) { / *... * / },
/ *... * /}].// watch vm.e.f's value: {g: 5}
'e.f': function (val, oldVal) { / *... * / }
}
})
vm.a = 2 // => new: 2, old: 1
Copy the code
Next, let’s sort out the process of Watch by following the source code
- Initialize watch in state.js
export function initState (vm: Component) {
vm._watchers = []
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)}if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch) initWatch(vm, opts.watch)
}
Copy the code
function initWatch (vm: Component, watch: Object) {
for (const key in watch) {
const handler = watch[key]
if (Array.isArray(handler)) {
for (let i = 0; i < handler.length; i++) {
createWatcher(vm, key, handler[i])
}
} else {
createWatcher(vm, key, handler)
}
}
}
Copy the code
Here, several ways of writing watch are adapted. CreateWatcher is finally called
function createWatcher (vm: Component, key: string, handler: any) {
let options
if (isPlainObject(handler)) {
options = handler
handler = handler.handler
}
if (typeof handler === 'string') {
handler = vm[handler]
}
vm.$watch(key, handler, options)
}
Copy the code
Here we see that the watch function is called, so where is this function defined? Where is the watch function defined in the stateMixin function? Where is the watch function defined in the stateMixin function? Watch is already mounted to the VM in the stateMixin function
Vue.prototype.$watch = function (
expOrFn: string | Function,
cb: Function, options? :Object
) :Function {
const vm: Component = this
options = options || {}
options.user = true
const watcher = new Watcher(vm, expOrFn, cb, options)
if (options.immediate) {
cb.call(vm, watcher.value)
}
return function unwatchFn () {
watcher.teardown()
}
}
Copy the code
Here we see that the $watch function returns a function. The returned function execution cancels the added observation. Const watcher = new watcher (VM, expOrFn, CB, options) adds observed values, and corresponding callback functions. For details, please refer to the previous article juejin.cn/post/699458…