src
├─compiler 编译相关
├─core Vue 核心库
├─platforms 平台相关代码
├─server SSR,服务端渲染
├─sfc .vue 文件编译为 js 对象
└─shared 公共的代码
vue采用flow静态类型检查器
调试, vue 采用rollup打包工具,设置 sourcemap,package.json 文件中的 dev 脚本中添加参数 --sourcemap
"dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web-
full-dev"
UMD | CommonJS | ES Module | |
---|---|---|---|
Full | vue.js | vue.common.js | vue.esm.js |
Runtim-only | vue.runtime.js | vue.runtime.common.js | vue.runtime.esm.js |
Full(production) | vue.min.js | - | |
Runtime-only(production) | vue.runtime.min.js | - |
完整版:同时包含编译器和运行时的版本。
编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。
运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。基本上就是除去编译器的其它一切。
UMD:UMD 版本可以通过 标签直接用在浏览器中。jsDelivr CDN 的 https://cdn.jsdelivr.net/npm/vue 默认文件就是运行时 + 编译器的 UMD 版本 (
vue.js
)。
CommonJS:CommonJS 版本用来配合老的打包工具比如 Browserify 或 webpack 1。这些打包工具的默认文件 (pkg.main
) 是只包含运行时的 CommonJS 版本 (vue.runtime.common.js
)。
ES Module:从 2.6 开始 Vue 会提供两个 ES Modules (ESM) 构建文件:
为打包工具提供的 ESM:为诸如 webpack 2 或 Rollup 提供的现代打包工具。ESM 格式被设计为可以被静态分析,所以打包工具可以利用这一点来进行“tree-shaking”并将用不到的代码排除出最终的包。为这些打包工具提供的默认文件 (pkg.module
) 是只有运行时的 ES Module 构建 (vue.runtime.esm.js
)。
为浏览器提供的 ESM (2.6+):用于在现代浏览器中通过 直接导入。****
寻找入口文件
查看 dist/vue.js 的构建过程
其实可以执行yarn dev文件 查看打包结果也可以直接查看入口文件
执行构建
npm run dev
# "dev": "rollup -w -c scripts/config.js --sourcemap --environment
TARGET:web-full-dev"
# --environment TARGET:web-full-dev 设置环境变量 TARGET
script/config.js 的执行过程
作用:生成 rollup 构建的配置文件
使用环境变量 TARGET = web-full-dev
// 判断环境变量是否有 TARGET
// 如果有的话 使用 genConfig() 生成 rollup 配置文件
if (process.env.TARGET) {
module.exports = genConfig(process.env.TARGET)
} else {
// 否则获取全部配置
exports.getBuild = genConfig
exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
}
genConfig(name)
根据环境变量 TARGET 获取配置信息
builds[name] 获取生成配置的信息
// Runtime+compiler development build (Browser)
'web-full-dev': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.js'),
format: 'umd',
env: 'development',
alias: {
he: './entity-decoder' },
banner
},
resolve()
const aliases = require('./alias')
const resolve = p => {
// 根据路径中的前半部分去alias中找别名
const base = p.split('/')[0]
if (aliases[base]) {
return path.resolve(aliases[base], p.slice(base.length + 1))
} else {
return path.resolve(__dirname, '../', p)
}
}
通过调用栈的方式查看$mount在哪里调用
问题:以下代码页面渲染的结果是
new Vue({
el: '#app',
template: '我是template
',
render (h) {
return h('h1', '我是reder渲染的')
},
})
分析:可以通过源码中的 if(!options.render)来判断,这句话的作用是如果render不存在,就会将template转换成render函数
Vue阅读源码需要注意的事项
vscode会出现红色波浪线报错 和 源码没有高调的情况
需要做的就是在vue项目的根目录建立.vscode/settings.json
{
// 设置不检查js的语法问题,防止flow报错
"javascript.validate.enable": false
}
同时为vscode安装 Babel javascript 插件可以解决高亮的问题, 有一个缺陷就是不能跳转到源码的位置
Watcher主要分为三种:computed watcher、用户自定义watcher(侦听器)、渲染watcher
把html模板转换成render函数工具
Vue3.0 Template Explorer
Vue2.x Template Explorer
_c 函数定义路径:src\core\instance\render.js
_m, _v, _s函数的定义路径:src\core\instance\render-helpers\index.js
AST抽象语法树
抽象语法树简称AST
使用对象的形式描述树形的代码结构
此处的抽象语法树是用来描述树形结构的HTML字符串
astexplorer 抽象语法树查看
首先需要说明diff算法的原理
老开始节点和新开始节点对比
老结束节点和新结束节点对比
老开始节点和新结束节点对比
老结束节点和新开始节点对比
上述情况都不满足才会老节点找新节点存在的索引
不设置或者设置key为index索引值,当往数组中splice插入一个元素时,会在updateChildren方法中,里面的sameVnode方法会判断为同一个vnode,不断比较老开始节点和新开始节点,索引向后移动,子节点会多次操作dom消耗性能。
function sameVnode (a, b) {
return (
a.key === b.key && (
(
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
) || (
isTrue(a.isAsyncPlaceholder) &&
a.asyncFactory === b.asyncFactory &&
isUndef(b.asyncFactory.error)
)
)
)
}