Life and freedom Ge Lin ——— Draw by Razzh

Vue 响应式流程

Sep 27 · 4 min

#前言

这个系列是用来记录笔者观看 Vue 源码的一些理解,可能理解会有些偏差,但过一段时间再看 Vue 源码,可能又会有新的理解,所以会反复勘误。

本文以 Vue 2.16.4 版本简述在数据更新时,Vue 响应式系统内部做了哪些事才让视图得以更新。

#从一个例子开始

  new Vue({
    el: "#app",
    template: `
      <div>
        <span>{{ name }}</span>
        <button @click="name = '李四'">
          点击更新视图
        </button>
      </div>
    `,
    data() {
      return {
        name: '张三'
      }
    },
  })

当我们点击按钮时,视图会发生更新,会触发 set 函数,收集依赖放入一个叫 subs 数组,最终调用 dep.notify 方法, notify 方法中会对 subs 依赖数组进行 update 操作,我们知道 Vue 的渲染机制是组件为单位,基于 JavaScript 的事件循环机制异步渲染的,所以在数据变化后,我们不能立刻更新视图,而是将它保存在一个队列 queue 中,我们执行 queueWatcher 方法,将渲染 watcher 放入队列中。

之后会执行 nextTick 方法将 flushSchedulerQueue 方法(最终执行队列的函数)作为参数传入,并放入一个 callback 数组中,在 nextTick 方法中比较关键的方法就是 timerFunc 方法了,在这里,它会对根据环境判断来降级选取适合的宏/微任务来对视图进行异步更新的操作,降级策略如下:

Promise > MutationObserver > setImmediate > setTimeout

之后等待页面的代码全都 mutation 变动完成后, flushCallbacks 才会执行,它通过循环 callbacks 来分别执行 flushSchedulerQueue ,它会循环执行 watcher queue 去执行 watcher.get 方法,里面的 this.getter 实际上就是 updateComponent 方法。

let updateComponent = () => {
  vm._update(vm._render(), hydrating)
}

可以看到它会先执行 vm._render 方法,会经过3个步骤生成 Render 函数

  • parse 生成 AST 树
  • optimize 为 AST 树加上 static 属性
  • generate 将 AST 树转换为 render 函数

具体过程可以在这里可以看到

之后就会执行 vm._update 方法,最终经过 patch 方法,给 DOM 打上 "补丁",修改页面上的数据。

#总结

image

笔者在看完源码后画了这张流程图,希望对你理解 Vue 响应式流程会一定帮助。

浙ICP备2024129591号-1
春秋(Live) - 张敬轩
--:-- / --:--
  1. 1春秋(Live)张敬轩
  2. 2不吐不快(live)张敬轩
  3. 3男孩最痛(live)张敬轩
  4. 4粤语残片(live)陈奕迅
  5. 5几分之几(live)卢广仲
  6. 6地球很危险古巨基
  7. 7樱花树下(live)张敬轩

春秋 (Live) - 张敬轩 (Hins Cheung)

词:林夕

曲:Edmond Tsang

那夜谁将酒喝掉

因此我讲得多了

然后你摇着我手拒绝我

动人像友情深了

我没权终止见面

只因你友善依然

仍用接近甜蜜那种字眼通电

没人应该 怨地怨天

得到这结局

难道怪罪神没有更伪善的祝福

我没有为你伤春悲秋不配有憾事

你没有共我踏过万里

不够剧情延续故事

头发未染霜 着凉亦错在我幼稚

应快活像个天使

有没有运气再扮弱者 玩失意

有没有道理为你落发

必须得到世人同意

心灰得极可耻 心伤得无新意

那一线眼泪 欠大志

爱若能堪称伟大 再难挨照样开怀

如令你发现为你而活到失败

令人不安 我品性坏

我没有为你伤春悲秋不配有憾事

你没有共我踏过万里

不够剧情延续故事

头发未染霜 着凉亦错在我幼稚

应快活像个天使

有没有运气再扮弱者玩失意

有没有道理为你落发

必须得到世人同意

心灰得极可耻 心伤得无新意

那一线眼泪 欠大志 太没意思

若自觉这叫痛苦未免过份容易

我没有被你改写一生怎配有心事

我没有被你害过恨过

写成情史 变废纸

春秋只转载要事

如果爱你欠意义

这眼泪 无从安置

我没有运气放大自私的失意

更没有道理在这日

你得到真爱制造恨意

想心酸 还可以 想心底 留根刺

至少要见面上万次