我对于深入响应式原理的理解

现在是19年5月27号下午7点,今天我们班新来了一个老师--赵老师,第一天他给我们布置的作业是在博客园上写一篇关于 深入响应式原理 的文章,所以我来到这写下我人生第一篇博客《我对于深入响应式原理的理解》,主要的参考对象就是“
https://cn.vuejs.org/v2/guide/reactivity.html#%E5%BC%82%E6%AD%A5%E6%9B%B4%E6%96%B0%E9%98%9F%E5%88%97”。


Vue最独特的特性之一,是其非侵入性的响应式系统(还要了解一下),那么它的实现原理有又是如何呢?

如何追踪变化

先来个官网的图镇一下楼吧

当我们把一个普通的 JavaScript 对象传入到Vue实例作为 data 选项时,Vue会遍历这个对象所有的属性,并使用Object.defineProperty 方法将这些属性全部转化为 getter/setter,(其中Object.defineProperty这个特性是无法使用低级浏览器中的方法来实现的,所以Vue不支持IE8以及更低版本的浏览器)
虽然这些 getter/setter 对于用户来说是不可见的,但是在内部它们让Vue可以追踪依赖,在属性被访问和修改时通知变更。
每一个组件实例都会对应一个 watcher 实例,它会在组件渲染到虚拟DOM树的过程中把“接触(Touch)”过的数据属性记录为依赖,用 getter 收集依赖,之后当依赖项的 setter 被触发时,会通知 watcher ,从而让它关联的组件重新渲染。


检测变化的注意事项

受现代 JavaScript 的限制(还要了解一下),Vue 无法检测到对象属性的添加和删除,因为 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的,在 data 外的是非响应式的。举个栗子:

let vm = new Vue({
    data: {
        a: 1
    }
})
vm.a = 2   // 响应式的
vm.b = 3  // 非响应式的
  1. 对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性,解决方法有两个:
    第一个可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性;第二个是使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:
Vue.set(vm.someObject, 'b', 2)

Vue.$set(vm.someObject, 'b', 2)
  1. 有时我们需要使用 Object.assign() 或  _.extend() 等方法来为已有的对象赋值多个新属性,但是这些属性不会被触发更新,解决的方法是:用原对象与要混合进去的对象的属性一起创建一个新的对象:
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })` 
this.someObject = Object.assign({},this.someObject, { a: 1, b: 2 })

声明响应式属性

由于 Vue 不允许动态添加根级响应式属性,所以我们必须在初始化实例前声明所有根级响应式属性,可以先声明一个空值 msg,在后边在赋值给 msg ,假如我们没有在 data 选项中声明 msg ,Vue 会警告我们渲染函数正在访问的属性是不存在的。

var vm = new Vue({ 
    data: { 
        // 声明 message 为一个空值字符串  
        msg: ' '
    }, 
    template: '<div>{{ msg }}</div>' 
}) 
// 之后设置 `msg` 
vm.msg = 'Hello!'

原因:它可以消除在依赖项跟踪系统中的一类 边界情况(上面提过),也使 Vue 实例可以更好地配合 类型检查系统(还要了解一下) 工作。更重要的是可以提高 代码可维护性:data 对象就像组件状态的结构 (schema)。提前声明所有的响应式属性,可以更方便在未来修改组件代码或让其他开发人员阅读和理解。


还有一些地方我也还没有弄懂的,由于时间关系(明天要检查的...),我暂时还没有说明白,等以后有时间了,我还会回来在修改的,see you

猜你喜欢

转载自www.cnblogs.com/mmshaohu/p/10933389.html