深入响应式原理——vue.js

  非侵入性的响应式系统是Vue最独特的特性之一。 那么非侵入性的响应式系统是什么呢? 

  Vue是mvvm框架。而module仅仅只是普通的JavaScript对象。当你修改这些对象时,视图也会进行更新。这就是非侵入性的响应式。 

  那么响应式底层原理是什么呢?

  简单说:当你把一个普通的JavaScript对象传入Vue实例作为data时,Vue将会遍历这个对象的所有属性。在遍历时会使Object.defineProperty把这些属性全部转为getter或者setter。由于Object.defineProperty是ES5中一个无法shim的特性,因此Vue不支持IE8以及更低版本的浏览器。

  当然getter/setter对用户是不可见的,但是Vue能够在内部通过它们追踪依赖。所以当属性被读写时,Vue也能及时的变更属性。

  那么Vue是如何在内部追踪依赖呢?

  其实每个组件实例都对应一个watcher实例,它会在组件渲染的过程中把监听到的数据属性记录为依赖。之后当该依赖的setter被触发时,会反馈给watcher,使该依赖和相关联的组件重新渲染。

 

  以下是图解:

 

    当属性检测时,应当注意如下几项:

    一、由于Object.observe 被废弃,Vue无法检测到对象属性的添加或删除操作。但是Vue会在初始化实例 对象时执行getter/setter转化。也因此属性必须写在data对象上,只有如此Vue才会将该属性传唤成响应式。

    二、对于已经创建的实例,Vue是 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性。例如,

Vue.set(vm.someObject, 'b', 2)

还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:

this.$set(this.someObject,'b',2)

有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新属性不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的属性一起创建一个新的对象。

由于 Vue 不允许动态添加根级响应式属性,所以你必须在初始化实例前声明所有根级响应式属性,哪怕只是一个空值:

如果你未在 data 选项中声明 message,Vue 将警告你渲染函数正在试图访问不存在的属性。

这样的限制在背后是有其技术原因的,它消除了在依赖项跟踪系统中的一类边界情况,也使 Vue 实例能更好地配合类型检查系统工作。但与此同时在代码可维护性方面也有一点重要的考虑:data 对象就像组件状态的结构 (schema)。

提前声明所有的响应式属性,可以让组件代码在未来维护时,给其他开发人员阅读时更易于理解。

 

posted @ 2019-05-27 13:20  名称已重置  阅读(131)  评论(0编辑  收藏  举报