vue 的响应式原理

这次我们一起做一个最小的 vue

首先我们要明白几个概念。数据驱动,响应式原理,发布订阅模式和观察者模式。

数据驱动

数据响应式,双向绑定,数据驱动。

数据响应式:数据模型是普通的 JS 对象,数据变,视图变。

双向绑定:数据变,视图变。视图变,数据变。如 v-moudle.

数据驱动:只管数据变,数据怎么渲染到视图中,不需要理会。这也是为什么 MVVM 框架火热。

响应式核心原理

vue 2.x :按照官网的说法是基于 object.defineProperty (不兼容 IE8 )把 data 中的属性遍历,转化为 getter setter

object.defineProperty :   https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

具体代码如下图 2.1

图 2.1

vue 3.x :是基于 ES6 中的 Proxy ,因为它针对象,而不是属性,所以面对多个对象可以省去遍历

Proxy 可学习阮一峰老师整理的内容       https://es6.ruanyifeng.com/#docs/proxy

代码如下图 2.2

图 2.2


发布订阅模式

在一个“信息中心”里存在发布者和订阅者两种角色,当有新的消息,发布着会进行推送,订阅者会进行接收。如图 2.3

图 2.3

实现 vue $on  $emit 见图2.4

图2.4

观察者模式

没有“信息中心”,目标(发布者)需要知道观察者(订阅者)的存在。目标中存储观察者名单 subs,还有两个方法, addSub() 添加观察者, notify() 当事件发生调用观察者的      update() 方法

代码见下图2.5

图2.5

好,在梳理上述概念时候,想必大家对 vue 最基本的构成也就有了一个大概认知。

首先一个 vue 类型对象,负责注入数据,把数据转换成  getter setter ,调用 observer  和  compiler 

observer 数据劫持监听数据变化,通知 dep(发布者)。

compiler 解析指令,替换插值表达式。

dep 负责添加观察者,并调用观察者 update

watcher 更新视图。

综上可总结出 关系图2.6

图2.6

我们先创建一个 使用了 vue 功能的模板,如下图 2.7

图 2.7

我们来回想一下 vue 的基本构造。

每个 vue 实例下边都包含了 options data el 三个属性。

根据 图2.6 ,以及上述总结,我们可以得知 vue 实现了什么以下四步功能。

1. 通过属性保存选项的数据

2. 把 data 中的成员转换成 getter setter ,注入到 vue 实例中

3. 调用 observer 对象,监听数据的变化

4. 调用 compiler 对象,解析指令和差值表达式

有了以上四步,逻辑就很清晰了。然后可以得到代码 图2.8

 图2.8

除了红框里的内容,其他的代码在上边都解释了,这里也就不做赘述。

接下来我们来解决红框里的两个类。

首先是 Observer ,我们想一下它做了什么 ,数据劫持监听数据变化,并通知 dep(发布者)。

所谓的监听数据变化。也就是把 data 中的数据转化为 gettersetter ,方便 this 调用。但是这里与 vue 类中不同的是。 Observer 还和 Dep 关联。

我们来想一下, Dep 做了什么,无非就是添加观察者和发布。

添加的时机显然就是生成 getter 的时候, 发布就是 set 的时候。由此得出代码 图2.9

 图2.9

好,出了上述代码,大家一定对红框框里的 dep 比较感兴趣。对吧,你凭什么就突然一个 Dep.target ,然后就开始添加观察者,这显然不讲道理。

好,讲道理之前我们先看两个其他的类,一个 Dep ,一个 watcher

Dep 无非就是添加和发布,上边说了,不再赘述,直接上才艺,图2.10

图2.10

简单朴实不难懂。然后是 watcher ,它是来干嘛的,显然是监控数据变化。数据变化了然后编译到页面上。不难得出 watcher 的构成就是,属性,以及更新 DOM 的函数。

想要更新 DOM ,就少不了 Vue 实例和变化的属性名称,为了方便处理不同节点以及减少数据重复传递,我们一般会在实例化 watcher 时传入处理函数。由此得出 图 2.11

图 2.11

这里就解释清楚为什么会有 Dep.target && dep.addSub(Dep.target) 这样的代码了。

最后一部分,也就是剩下的 compiler 类了,它主要就是用来编译节点,根节点 el ,实例 vm 。这都是必须的没什么好说的,设下的功能就是为了编译。

vue 中的节点中我们只需要处理两种,文本节点和带有 v- 指令的元素节点,所以整体代码结构如下图,2.12.

图,2.12.

三个判断函数,如下图2.13,

图2.13,

主函数,根据条件进行一个函数分发和递归

图2.14

文本节点的处理,通过正则匹配 {} 中的内容,如果内容存在,就用他的值,替换到 node.textcontent 中,同时创建一个 watcher 对象对该数据的后续变化进行监听并处理。

图2.15

编译节点,遍历属性节点,找到是 v- 指令的,进行编译,这里通过 update 函数进行了一次分发,因为使用 if 分发太麻烦了,所有制令都要占行数,

图2.16

这两个函数也比较简单,就是根据情况进行一个修饰,

图2.17

把写好的类引入到 index 里,好,大公告成。

学了就问老板要涨薪,隔壁员工都馋哭了!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容