watch
vm.$watch(expOrFn,callback,[options])
功能
观察Vue实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式值接收监督的键路径
参数
- exOrFn:要监视的$data 中的属性,可以说表达式或函数
- callback:数据变化后执行的函数
函数:回调函数
对象:具有handler属性(字符串或者函数),如果该属性为字符串则methods中相应的定义 - options:可选的选项
deep: 布尔类型,深度监听
immediate: 布尔类型,是否立即执行一次回调函数
示例
const vm = new Vue({
el:"#app",data:{
user:{
fisrtName: 'aaaa',lastName: 'bbbbb'}}
})vm.$watch('user',function(newValue,oldValue){
this.user.firstName = newValue.firstName + " " + newValue.lastName
},{
immediate: true,deep: true
})
三种类型的Watcher对象
- 没有静态方法,因为$watch方法中要是用Vue的实例
- Watcher分三种:计算属性Watcher,用户Watcher(侦听器)、渲染Watcher
创建顺序:计算属性Watcher,用于Watcher,渲染Watcher - vm.$watch()
src/core/instance/state.js
部分代码
export function initState (vm: Component) {
vm._watchers = []const opts = vm.$optionsif (opts.props) initProps(vm, opts.props) // 初始化props,并且通过defineReactive函数将值转换为set,getif (opts.methods) initMethods(vm, opts.methods) // 将选项中的methods注入到vue实例,if (opts.data) {
initData(vm) // } else {
observe(vm._data = {
}, true /* asRootData */) //转换成响应式数据} if (opts.computed) initComputed(vm, opts.computed) // 初始化computedif (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch) // 初始化watch}
}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)}}
}function createWatcher (vm: Component,expOrFn: string | Function,handler: any,options?: Object
) {
if (isPlainObject(handler)) {
// hundler是回调函数,就是对应传入方法options = handlerhandler = handler.handler}if (typeof handler === 'string') {
handler = vm[handler]}return vm.$watch(expOrFn, handler, options)
}export function stateMixin (Vue: Class<Component>) {
// flow somehow has problems with directly declared definition object// when using Object.defineProperty, so we have to procedurally build up// the object here.const dataDef = {
}dataDef.get = function () {
return this._data }const propsDef = {
}propsDef.get = function () {
return this._props }if (process.env.NODE_ENV !== 'production') {
dataDef.set = function () {
warn('Avoid replacing instance root $data. ' +'Use nested data properties instead.',this)}propsDef.set = function () {
warn(`$props is readonly.`, this)}}Object.defineProperty(Vue.prototype, '$data', dataDef)Object.defineProperty(Vue.prototype, '$props', propsDef)Vue.prototype.$set = setVue.prototype.$delete = delVue.prototype.$watch = function (expOrFn: string | Function,cb: any,options?: Object): Function {
// 获取 Vue 实例的thisconst vm: Component = thisif (isPlainObject(cb)) {
// 判断如果 cb 是对象执行createWatcherreturn createWatcher(vm, expOrFn, cb, options)}options = options || {
}// 标记为用户 watcheroptions.user = true// 创建用户 watcher 对象const watcher = new Watcher(vm, expOrFn, cb, options)// 判断 immediate 对象if (options.immediate) {
// 立即执行一次cb回调,并把当前值传入try {
cb.call(vm, watcher.value)} catch (error) {
handleError(error, vm, `callback for immediate watcher "${
watcher.expression}"`)}}// 返回取消监听的方法return function unwatchFn () {
watcher.teardown()}}
}