JavaScript 数据劫持——观察数据的变化 & Vue 3 会升级使用 Proxy
- 数据劫持?
- Observer 数据观察
- 数据拦截器
如何实现修改一个对象成员就修改了DOM?
const data = {
message: 'Hello World'
}
// 监视 data.message 的改变
// watch('data.message', () => {
// dom.xxx = xxx
// })
data.message = 'hello'
// data.message = xxx 不仅仅对数据进行了修改,还操作了 DOM
//
答案是:JavaScript 数据劫持,或者说是 JavaScript 对象属性拦截器。
什么是数据劫持(属性拦截器)?
说白了就是:观察数据的变化。
- Object.defineProperty
- ECMAScript 5 中的一个 API
- Vue 1 和 Vue 2 中使用的都是 Object.defineProperty
- Proxy
- ECMAScript 6 中的一个 API
- 即将升级的 Vue 3 会升级使用 Proxy
- Proxy 比 Object.defineProperty 性能要更好
深入响应式原理:https://cn.vuejs.org/v2/guide/reactivity.html
如何追踪变化:
当你把一个普通的 JavaScript 对象传入 Vue 实例作为
data
选项,Vue 将遍历此对象所有的属性,并使用Object.defineProperty
把这些属性全部转为 getter/setter。Object.defineProperty
是 ES5 中一个无法 shim (ES5之前的语法无法解析)的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据属性记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
检测变化的注意事项
Vue 无法检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data
对象上存在才能让 Vue 将它转换为响应式的。例如:
扫描二维码关注公众号,回复:
10015361 查看本文章
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应式的
vm.b = 2
// `vm.b` 是非响应式的
对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value)
方法向嵌套对象添加响应式属性。例如,对于:
Vue.set(vm.someObject, 'b', 2)
您还可以使用 vm.$set
实例方法,这也是全局 Vue.set
方法的别名:
this.$set(this.someObject,'b',2)
et实例方法,这也是全局
Vue.set` 方法的别名:
this.$set(this.someObject,'b',2)