关于一些Vue的文章。(7)

原文链接我的blog,欢迎STAR。

首先安利一波福利,有没有用vscode的小伙伴?推荐一个神奇的字体,自从用了这个字体,敲代码效率简直上天了。先上图看看效果:

全等
全等
箭头函数
箭头函数
小于等于
小于等于

还有其他许多,就不一一列举出来了。
有没有看上了的?
没有我等下再来问。

这次推荐的一篇文章来自,阅读文章有利于加深对Vue程序结构的了解,虽然是 1.0版本,不过好在 2.0 版本保留了绝大部分 1.0 的API。

在这篇文章里我将是这几个月来对 Vue 学习的一个小结。


思路

Vue 和其他的 MVVM 思路是类似的:

主要是为了实现三个过程:

  1. Observer: 通过Observer对data进行监听,并且提供订阅某个数据项的变化的能力。利用Object.defineProperty, 将data里的每个属性全部转化为getter/setter,已遍拦截对象赋值与取值操作;

  2. Compiler: 将template 解析为 render()方法;

  3. watcher: Compiler 的解析结果与 Observer 结合起来,在 Observer 监听到数据发生改变时,接受通知,进而触发 re-render, 重新渲染DOM。


new Vue

我们从 new Vue 开始,

上图即是官网给出的一张生命周期图,主要是四个过程:

  • create: 在 new Vue() 时会运行,创建出 Vue 对象。
  • mount: 会根据 el, template, render 等,生成 Vnode, 完成 diff 算法后挂载到 DOM 上。
  • updata: 当数据发生改变时,会重新渲染 DOM。
  • destory: Vue 销毁时会运行。

现在,我们进入源码,分析具体的实现:

  • Create: 首先运行new vue()的时候,会进入_init
    其中关键部分的代码如下:

可以看出在 beforeCreatecreated 只有initState, initState 是用于实现data observerevent/watcher

  • Mount: 在_init最后,会运行 vm.$mount 方法:

具体 vm.$mount 的分析,请看上篇。最后进行了 render(), 从而会有Vnode, 经过 DIFF 算法后会有真实 DOM ;

  • Update: DOM 之后,会进行update方法:

    vm._watcher = new Watcher(vm, () => {
      vm._update(vm._render(), hydrating)
    }, noop)
    

将以上用一张序列图表示也就是:


深入响应式原理 (Observer, watcher)

MVVM 框架有一个很重要的特征:就是当数据放生变化后,会自动更新对应的DOM节点。 Vue 是怎么实现的?

以上是来自官网的一张图。

前面提到在 beforeCreatecreated 两个生命周期钩子函数之间会运行 initState() 方法。

initState() 源码里:

在这个方法里,会对props, data, computed 等属性利用 Object.defineProperty 将这些属性全部转化为 getter/setter

我们以 initData() 为例子进行分析:

这里有一个值得注意的地方, proxy(vm, "_data", keys[i]), 设置 vm._data为代理,具体作用是实现 vm.a === vm._data.a

initData()最后 会进行 observe(data, this)

observe()里,既是转化为 getter/setter

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      const value = getter ? getter.call(obj) : val
      // 只有在有Dep.target时才说明是Vue内部依赖收集过程触发的getter
      // 那么这个时候就需要执行dep.depend(),将watcher(Dep.target的实际值)添加到dep的subs数组中
      // 对于其他时候,比如dom事件回调函数中访问这个变量导致触发的getter并不需要执行依赖收集,直接返回value即可
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          // 如果value在observe过程中生成了ob实例,那么就让ob的dep也收集依赖
          childOb.dep.depend()
        }
        if (isArray(value)) {
            //如果数组元素也是对象,那么他们observe过程也生成了ob实例
            dependArray(value)
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      var value = getter ? getter.call(obj) : val
      if (newVal === value) {
        return
      }
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      // observe 这个新数据
      childOb = observe(newVal)
      // 通知到dep 进行数据更新。
      dep.notify()
    }
  })
  

到这个时候,Observer 监听已经完成,如果数据更新,我们会进行 dep.notify() 方法:

dep.notify() , 方法里会执行update()

update() , 中会进行
queueWatcher() 方法:

queueWatcher(), 目的是通过 nextTicker 来执行 run()

run() 里,其实就是执行 this.get() 方法:

get() 方法里,会运行 this.getter(), 方法来更新 DOM 。

this.getter()方法是啥?

再就是上文中所提到的new Watcher(), 的第二个参数。

vm._watcher = new Watcher(vm, () => {
  vm._update(vm._render(), hydrating)
}, noop)

而在 new Watcher 构造完成后,会调用 this.get() ,触发 this.getter(),方法触发 DOM 更新。

具体可以看watcher.js:

截一个关键代码部分的图:

以上,用一张序列图来表示,既就是:

对以上总结:

  • 首先 _init ,对属性利用 Object.defineProperty,将属性转为 getter/setter,在 setter 方法里,会调用 dep.notify()
  • vm 设置 new Watcher
  • data 变化时,进行数据跟新。

完。

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

推荐阅读更多精彩内容