【Vue原理】响应式原理 - 白话版




【Vue原理】响应式原理 - 白话版


本文打算 白话文的形式讲解 Vue 的响应式系统原理,尽可能不涉及源码。
数组

只阐述工做流程,不想内容过多过于繁杂,致使你们会没有什么阅读的兴趣。bash

因此我从此打算把每个内容分红 白话版和 源码版。函数

白话版,就是让你们不用花费太多脑力,不用消耗太多时间,就能轻松地看完并大体了解内容。学习

有时间精力的人能够阅读源码版 ,而后本身参考源码,来进行研究学习。有什么错误的地方,感谢你们可以指出ui





响应式系统

咱们都知道,只要在 Vue 实例中声明过的数据,那么这个数据就是响应式的。spa

什么是响应式,也便是说,数据发生改变的时候,视图会从新渲染,匹配更新为最新的值。设计

也正是由于这个系统,让咱们能够脱离界面的束缚,只须要操做数据。code


咱们能够问出下面三个问题cdn


一、Vue 是怎么知道数据改变?对象

二、Vue 在数据改变时,怎么知道通知哪些视图更新?

三、Vue 在数据改变时,视图怎么知道何时更新?


问题的谜底将在下面一一解开  



如今,我将会讲解三个重要的概念

Object.defineProperty,依赖收集,依赖更新


Object.defineProperty

这个方法,是 Vue 响应式系统的精髓,骨髓,脑髓

使用 Object.defineProperty 能够为对象中的每个属性,设置 get 和 set 方法


Object.defineProperty 能够为属性设置不少特性,例如 configurable,enumerable,可是如今不过多解释,重点只放在 get 和 set


那么 get 和 set 方法有什么用?

get 值是一个函数,当属性被访问时,会触发 get 函数

set 值一样是一个函数,当属性被赋值时,会触发 set 函数


举个例子

var obj={    
    name:"神仙朱"
}
Object.defineProperty(obj,"name",{
    get(){        
        console.log("get 被触发")
    },
    set(val){        
        console.log("set 被触发")
    }
})
复制代码

当我访问 obj.name 时,会打印 ' get 被触发 '

当我为 obj.name 赋值时,obj.name = 5,会打印 ' set 被触发 '


这即可以回答了我开篇的第一个问题

Vue 是怎么知道数据改变的呢?

恩,Vue 在 属性的 set 方法中作了手脚,于是当数据改变时,触发 属性的 set 方法,Vue 就能知道数据有改变



依赖收集

简单地说

data 中的声明的每一个属性,都拥有一个数组,保存着 谁依赖(使用)了 它


举个例子

new Vue({    
    data(){        
        return {            
            name:"神仙朱"        
        }    
    }
})
复制代码

而后 页面A 引用了name

<div>{{name}}</div>
复制代码

此时,name 把 页面 A 存在它的后宫中(这个页面依赖我)


为何呢?

由于它知道谁依赖它以后,它就能够在发生改变的时候,通知 依赖它的页面,从而让页面完成更新


TIP

实际上,会依赖 name 的地方,不仅是页面,还会有 computed,watch.... 等等,可是这里咱们所有使用页面一词替代


这就是依赖收集,把 依赖了我(使用了个人东西),通通保存起来。

但是,保存在哪里,具体保存的是什么东西,咱们这里暂时不深刻,由于这是白话文。

我按上面的例子,从Vue 内部打印一份数据供你们简单了解便可

能够看到,name 属性,使用了 一个 dep 保存了 页面A 这个依赖,而保存的其实是 页面A的 Watcher。


TIP

简单说一下,watcher 是什么,每一个 Vue 实例都会拥有一个专属的 watcher,可用于实例更新


总结一下

一、data 中每一个声明的属性,都会有一个 专属的依赖收集器 subs

二、当页面使用到 某个属性时,页面的 watcher 就会被 放到 依赖收集器 subs 中


数据 是在何时进行 收集依赖 的呢?


答案是,ObjectdefineProperty - get

当 页面 A 读取了 name 时,会触发 name 的 get 函数,此时,name 就会保存 页面A 的 watcher 啦!


这即可以回答了我开篇的第二个问题

Vue 在数据改变时,怎么知道通知哪些视图更新?

恩,通知那些存在 依赖收集器中的 视图



依赖更新

依赖更新,就是,通知全部的依赖进行更新

通过上面的讲解,咱们都知道,每一个属性都会保存有一个 依赖收集器 subs

而这个 依赖收集器,是用来在 数据变化时,通知更新的

数据 是在 何时进行 依赖更新 的呢?


答案是,Object.defineProperty - set

以上面的 Vue 实例 为例

当 name 改变的时候,name 会遍历本身的 依赖收集器 subs,逐个通知 watcher,让 watcher 完成更新

这里 name 会通知 页面A,页面A 从新读取新的 name ,而后完成渲染


这即可以回答了我开篇的第二个问题

Vue 在数据改变时,视图怎么知道何时更新?

恩,在数据变化触发 set 函数时,通知视图,视图开始更新


简单总结

一、Object.defineProperty - get ,用于 依赖收集

二、Object.defineProperty - set,用于 依赖更新

三、每一个 data 声明的属性,都拥有一个的专属依赖收集器 subs

四、依赖收集器 subs 保存的依赖是 watcher

五、watcher 可用于 进行视图更新


最后

哈哈,最近好多的人都说我很高产,其实个人文章就是个人笔记,我作了不少笔记,可是个人笔记样式不堪入目,因此发文章须要排版,并且部份内容须要写得更加详细一些,所以须要更多的时间去验证研究,因此有时懒得发文章。

谢谢个人每个粉丝的支持,我一直之内容高质量,排版看得舒服 为目标,对待每一篇文章,因此很是耗时,可是我很认真。

若是发现有错误,说得不对的地方,很是感谢可以指出,本人会有重谢哈哈哈,很是欢迎一块儿探讨学习



相关文章
相关标签/搜索