vm.$watch
vm.$watch( expOrFn, callback, [options])
参数:
- {string | Function} expOrFn
- {Function | Object} callback
- {Object} [options]
- {boolean} deep (发现对象内部值的变化)
- {boolean} immediate( 立即以表达式的当前值触发回调,例:父组件给子组件 传值,最初绑定值时也执行函数)
返回值:{Function} unwatch
用法:
观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代。
watch的内部原理
vm.$watch其实是对Watcher的的一种封装
1 | // src/core/instance/state.js |
在dep(依赖列表)中收集每个watcher,同时在watcher中记录被添加到哪几个dep
- watcher和dep多对多的关系
- 如果watcher中的expOrFn参数是一个表达式,那么肯定只收集一个Dep
- 如果Watcher中的expOrFn参数是一个函数,此时如果该函数中使用了多个数据,那么这时的Watcher就被多个Dep收集
deep参数原理
触发当前这个被监听数据的收集依赖的逻辑之外,还要把当前监听的这个值在内的所有子值都触发一遍收集逻辑
// src/core/observer/watcher.js
traverse()必须在popTarget()
1 | const seenObjects = new Set() |
vm.$set
- vm.$set( target, propertyName/index, value )
参数**:
- {Object | Array} target
- {string | number} propertyName/index
- {any} value
返回值:设置的值。
用法:
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为 Vue 无法探测普通的新增属性 (比如
this.myObject.newProperty = 'hi'
)
vm.$set的具体实现其实在observer中抛出的set方法
1 | // src/core/observer/index.js |
Vue.delete
Vue.delete( target, propertyName/index )
参数**:
- {Object | Array} target
- {string | number} propertyName/index
用法:
删除对象的属性。如果对象是响应式的,确保删除能触发更新视图。这个方法主要用于避开 Vue 不能检测到属性被删除的限制,但是你应该很少会使用它。
手动更新
使用delete,手动更新dep
1 | delete this.obj.a |
原理
vm.$delete的具体实现其实在observer中抛出的del方法
1 | /** |