微信公众号: [大前端驿站]
关注大前端驿站。问题或建议,欢迎公众号留言。
这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战
Vue是当今最火的前端框架之一,是一套优秀的前端渐进式框架,它的简单易用性的特点也是众多前端工程师选择的原因。但是想要在众多Vue工程师中脱颖而出,其原理是必须要掌握的,接下来我们一起通过源码分析的角度来学习vue2的一些原理知识。
调试环境搭建
获取vue
掌握学习的方法很重要,我们先将vue2的源代码clone下来,然后看看部分重要的源码目录。
项目地址:https://github.com/vuejs/vue
git 执行:git clone https://github.com/vuejs/vue.git
当前版本:"2.6.14"
安装依赖
npm i
安装到phantom.js时如果特别慢,这时可以提前终止
安装rollup
npm i rollup -g
修改package.json中的dev脚本,添加sourcemap
"dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web- full-dev",
执行开发命令构建vue.js
npm run dev
注意目录不要有中文,不然构建可能会出现报错 构建完成后dist目录中会生成重新构建好的sourcemap的vue.js
修改examples/commit/index.html
<!-- <script src="../../dist/vue.min.js"></script> -->
<script src="../../dist/vue.js"></script>
打开index.html,我们可以看到sourcemap的调试便利之处
vue.js可以断点调试代码
术语解释:
- runtime: 仅包含运行时,不包含编辑器
- common: cjs规范,用于webpack1
- esm: ES模块,用于webpack2
- umd: 兼容cjs和amd,用于浏览器
目录结构
vue2源码目录,我们重点关注源代码目录
源代码子目录
入口
我们执行执行package.json中的dev脚本,分析脚本知道从scripts/config.js中找到目标环境为web-full-dev处123行
// 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
},
此处我们可以看到入口文件是web/entry-runtime-with-compiler.js,但是并没有找到web目录,这是我们可以想到大概是设置了别名,然后确实在scripts/alias.js中找到了
web: resolve('src/platforms/web'),
然后我们定位到了入口文件src/platforms/web/entry-runtime-with-compiler.js
整体流程
我们从入口文件一步步推导它引入了哪些文件,看看这些文件都做了哪些工作
platforms/web/entry-runtime-with-compiler.js
主要作用:扩展默认的$mount方法,处理template或者el选项
import Vue from './runtime/index'
...
const mount = Vue.prototype.$mount
...
platforms/web/runtime/index
安装web平台特有指令和组件 定义__patch__:补丁函数,执行patching算法进行更新 定义$mount:挂载vue实例到指定宿主元素(获得dom并替换宿主元素)
core/index.js
初始化全局api
Vue.set = set
Vue.delete = del
Vue.nextTick = nextTick
initUse(Vue) // 实现Vue.use函数
initMixin(Vue) // 实现Vue.mixin函数
initExtend(Vue) // 实现Vue.extend函数
initAssetRegisters(Vue) // 注册实现Vue.component/directive/filter
core/instance/index.js
定义Vue构造函数 定义Vue实例api
function Vue (options) {
// 构造函数仅执行了_init
this._init(options)
}
initMixin(Vue) // 实现init函数
stateMixin(Vue) // 状态相关api $data,$props,$set,$delete,$watch
eventsMixin(Vue) // 事件相关api $on,$once,$off,$emit
lifecycleMixin(Vue) // 生命周期api _update,$forceUpdate,$destroy
renderMixin(Vue)// 渲染api _render,$nextTick
core/instance/init.js
创建组件实例,初始化其数据、属性、事件等
initLifecycle(vm) // $parent,$root,$children,$refs
initEvents(vm) // 处理父组件传递的事件和回调
initRender(vm) // $slots,$scopedSlots,_c,$createElement
callHook(vm, 'beforeCreate')
initInjections(vm) // 获取注入数据
initState(vm) // 初始化props,methods,data,computed,watch
initProvide(vm) // 提供数据注入
callHook(vm, 'created')
$mount: mountComponent
执行挂载,获取vdom并转换为dom
new Watcher()
创建组件渲染watcher
updateComponent()
执行初始化或更新
update()
初始化或更新,将传入vdom转换为dom,初始化时执行的是dom创建操作
render(): src\core\instance\render.js
渲染组件,获取vdom
Vue初始化的整体流程
- new Vue()
- _init()
- $mount()
- mountComponent
- new Watcher()
- updateComponent()
- render()
- _update()
【分享、点赞、在看】三连吧,让更多的人加入我们~~