可以先从简版的vue开始,逐步过渡到实际源码。
- Roolup 和源码相同配置,基本目录结构
- Vue 数据响应式原理、渐进处理
- watch和computed
- Vue 模板编译
- diff
项目基本配置
vue使用 roolup打包
npm install @babel/preset-env @babel/core rollup rollup-plugin-babel rollup-plugin-serve cross-env -D
配置文件 rollup.config.js
import babel from 'rollup-plugin-babel';
import serve from 'rollup-plugin-serve';
export default {
input: './src/index.js',
output: {
format: 'umd', // 模块化类型
file: 'dist/umd/vue.js',
name: 'Vue', // 打包后的全局变量的名字
sourcemap: true
},
plugins: [
babel({
exclude: 'node_modules/**'
}),
process.env.ENV === 'development'?serve({
open: true,
openPage: '/public/index.html',
port: 3000,
contentBase: ''
}):null
]
}
babel配置文件 .babelrc
{
"presets": [
"@babel/preset-env"
]
}
项目启动命令
"scripts": {
"build:dev": "rollup -c",
"serve": "cross-env ENV=development rollup -c -w"
}
Vue基本封装思路
使用 class Vue
会让方法无法被分割,这里采用 function Vue(){}
原型方案,我们可以对 Vue.prototype.xx
进行文件分割。
初始化部分 设置为 initMixin() ,这样代码的风格:
import {initMixin} from './init';
function Vue(options) {
this._init(options);
}
initMixin(Vue); // 给原型上新增_init方法
export default Vue;
其中 init
的具体代码:
import {initState} from './state';
export function initMixin(Vue){
Vue.prototype._init = function (options) {
const vm = this;
vm.$options = options
// 初始化状态
initState(vm)
}
}
后续 initState 时候再去进行 prop method data compouted watch 的初始化,这样代码读起来更清晰,专注。
数据响应式
https://www.yuque.com/xinbao37/vue-source/vue2-reactive
Watcher和Computed
https://www.yuque.com/xinbao37/vue-source/vue2-watch-computed
模板编译
https://www.yuque.com/xinbao37/vue-source/template-compiler