likes
comments
collection
share

手写Vue2源码(一)—— 环境搭建

作者站长头像
站长
· 阅读数 49

前言

通过手写Vue2源码,更深入了解Vue; 在项目开发过程,一步一步实现Vue核心功能,我会将不同功能放到不同分支,方便查阅; 另外我会编写一些开发文档,阐述编码细节及实现思路; 源码地址:手写Vue2源码

目录结构

vue-code-analyze
├─ .babelrc
├─ .eslintrc.js
├─ dist                 // 打包后的源码
│  ├─ vue.js
│  └─ vue.js.map
├─ docs                 // 开发文档
│  └─ 1.导览.md
│  └─ ...
├─ LICENSE
├─ package-lock.json
├─ package.json
├─ public               // html文件
│  └─ index.html
├─ README.EN.md
├─ README.md
├─ rollup.config.js     // rollup配置文件
└─ src
   ├─ compiler          // 编译相关
   │  ├─ codegen.js
   │  ├─ index.js
   │  └─ parse.js
   ├─ global-api        // global-api相关
   │  └─ index.js
   ├─ index.js          // 入口文件
   ├─ init.js           // initeMixin(_init、$mount)
   ├─ lifecycle.js      // lifecycleMixin(_update、mountComponent)
   ├─ observer          // 响应式相关
   │  ├─ array.js
   │  ├─ index.js
   │  └─ watcher.js
   ├─ render.js         // renderMixin(_c、_v、_s、_render)
   ├─ state.js          // initState(initProps、initData...)
   ├─ util              // 工具函数
   │  ├─ index.js
   │  └─ next-tick.js
   ├─ utils.js
   └─ vdom              // 创建虚拟DOM、diff算法、渲染成真实DOM
      ├─ index.js
      └─ patch.js

环境搭建

使用rollup打包,安装依赖:

yarn add rollup rollup-plugin-babel rollup-plugin-serve -D

使用babel对代码进行转义:

yarn add @babel/core @babel/preset-env babel-eslint -D

创建babel配置文件.babelrc,创建eslint配置文件.eslintrc.js,创建rollup配置文件rollup.config.js

// rollup.config.js
import babel from 'rollup-plugin-babel'
import serve from 'rollup-plugin-serve'

export default {
    input: './src/index.js',    // 入口文件
    output: {
        format: 'umd',  // 支持amd 和 commonjs规范
        name: 'Vue',
        file: 'dist/vue.js',    // 输出文件
        sourcemap: true,
    },
    plugins: [
        babel({ // 使用babel进行转化,但是排除node_modules文件
            exclude: 'node_modules/**' // glob 语法;**表示任意文件
        }),
        // dev环境下在3000端口开启一个服务
        process.env.ENV === 'development'
            ? serve({
                open: true,
                openPage: '/public/index.html',
                port: 3000,
                contentBase: ''
            })
            : null
    ]
}

创建script命令:

"scripts": {
    "serve": "cross-env ENV=development rollup -c -w",
    "build:dev": "rollup -c"
},

分析一下我们做了什么:

  1. 使用rollup打包项目,入口文件是./src/index.js,出口是dist/vue.jsdist/vue.js.map
  2. 使用babel对源码进行转义
  3. 使用eslint
  4. 使用cross-env为命令行添加运行参数
  5. 使用rollup-plugin-serve,当处于development环境下,在3000端口创建一个服务,并在默认浏览器下打开/public/index.html页面
  6. /public/index.html中引入打包好的vue文件dist/vue.js

new Vue(options)到底做了什么

Vue其实是一个构造函数,new Vue(options)时创建了一个Vue实例;通过在构造函数及其prototype对象上添加属性/方法,实现Vue的功能。

Vue实现的功能有:

  1. 数据劫持
  2. 模板编译
  3. render函数生成VNode;初次渲染时,直接将VNode转化成真实DOM;更新时,Diff算法,局部更新
  4. 数据响应式(Dep、Watcher等)
  5. keep-alive、computed、watch等
  6. 全局API的实现:extend、filter等

创建构造函数Vue

// src/index.js
function Vue(options) {
    // new Vue创建实例时会调用_init()方法
    this._init(options)
}
return Vue

对构造函数进行扩展

import { initMixin } from "./init"
import { lifecycleMixin } from './lifecycle'
import { renderMixin } from './render'
import { initGlobalApi } from './global-api/index'

function Vue(options) {
    // new Vue创建实例时会调用_init()方法
    this._init(options)
}
initMixin(Vue) // 在原型上挂载_init()(initState(initData、initComputed等))、$mount()(compiler流程)
lifecycleMixin(Vue) // 在原型上挂载 _update()方法(第一次创建dom及更新dom(有diff过程))、mountComponent
renderMixin(Vue)  //  在原型上挂载_c、_v、_s、$nextTick、_render()方法
stateMixin(Vue);  // 定义Vue.prototype.$watch创建用户watcher
initGlobalApi(Vue); // initMixin(Vue.mixin(options))、初始化Vue.options、创建全局组件keep-alive、vue.component()、vue.directive()、vue.filter()等

export default Vue

系列文章

转载自:https://juejin.cn/post/7047685847193223205
评论
请登录