为什么写这篇vue的分析文章?
对于天资愚钝的前端(我)来说,阅读源码是件不容易的事情,毕竟有时候看源码分析的文章都看不懂。每次看到大佬们用了1~2年的vue就能掌握原理,甚至精通源码,再看看自己用了好几年都还在基本的使用阶段,心中总是羞愧不已。如果一直满足于基本的业务开发,怕是得在初级水平一直待下去了吧。所以希望在学习源码的同时记录知识点,可以让自己的理解和记忆更加深刻,也方便将来查阅。
目录结构
本文以vue的第一次 commit a879ec06 作为分析版本
├── build
│ └── build.js // `rollup` 打包配置
├── dist
│ └── vue.js
├── package.json
├── src // vue源码目录
│ ├── compiler // 将vue-template转化为render函数
│ │ ├── codegen.js // 递归ast提取指令,分类attr,style,class,并生成render函数
│ │ ├── html-parser.js // 通过正则匹配将html字符串转化为ast
│ │ ├── index.js // compile主入口
│ │ └── text-parser.js // 编译{{}}
│ ├── config.js // 对于vue的全局配置文件
│ ├── index.js // 主入口
│ ├── index.umd.js // 未知(应该是umd格式的主入口)
│ ├── instance // vue实例函数
│ │ └── index.js // 包含了vue实例的初始化,compile,data代理,methods代理,watch数据,执行渲染
│ ├── observer // 数据订阅发布的实现
│ │ ├── array.js // 实现array变异方法,$set $remove 实现
│ │ ├── batcher.js // watch执行队列的收集,执行
│ │ ├── dep.js // 订阅中心实现
│ │ ├── index.js // 数据劫持的实现,收集订阅者
│ │ └── watcher.js // watch实现,订阅者
│ ├── util // 工具函数
│ │ ├── component.js
│ │ ├── debug.js
│ │ ├── dom.js
│ │ ├── env.js // nexttick实现
│ │ ├── index.js
│ │ ├── lang.js
│ │ └── options.js
│ └── vdom
│ ├── dom.js // dom操作的封装
│ ├── h.js // 节点数据分析(元素节点,文本节点)
│ ├── index.js // vdom主入口
│ ├── modules // 不同属性处理函数
│ │ ├── attrs.js // 普通attr属性处理
│ │ ├── class.js // class处理
│ │ ├── events.js // event处理
│ │ ├── props.js // props处理
│ │ └── style.js // style处理
│ ├── patch.js // node树的渲染,包括节点的加减更新处理,及对应attr的处理
│ └── vnode.js // 返回最终的节点数据
└── webpack.config.js // webpack配置
从template到html的过程分析
我们的代码是从new Vue()开始的,Vue的构造函数如下:
constructor (options) {
// options就是我们对于vue的配置
this.$options = options
this._data = options.data
// 获取元素html,即template
const el = this._el = document.querySelector(options.el)
// 编译模板 -> render函数
const render = compile(getOuterHTML(el))
this._el.innerHTML = ''
// 实例代理data数据
Object.keys(options.data).forEach(key => this._proxy(key))
// 将method的this指向实例
if (options.methods) {
Object.keys(options.methods).forEach(key => {
this[key] = options.methods[key].bind(this)
})
}
// 数据观察
this._ob = observe(options.data)
this._watchers = []
// watch数据及更新
this._watcher = new Watcher(this, render, this._update)
// 渲染函数
this._update(this._watcher.value)
}
当我们初始化项目的时候,即会执行构造函数,该函数向我们展示了vue初始化的主线:编译template字符串 => 代理data数据/methods的this绑定 => 数据观察 => 建立watch及更新渲染
1. 编译template字符串
const render = compile(getOuterHTML(el))
其中compile的实现如下:
export function compile (html) {
html = html.trim()
// 对编译结果缓存
const hit = cache[html]
// parse函数在parse-html中定义,其作用是把我们获取的html字符串通过正则匹配转化为ast,输出如下
更新日志
2025年11月10日
2025年11月10日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]