# vue源码 开始啦
😃 从现在开始好好学习
# debug and start
- downLoad source code
- run
npm install
- alert
package.json
"scripts": {
"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev --sourcemap",
...
- example/chose index index
change
<script src="../../dist/vue.min.js"></script>
to
<script src="../../dist/vue.js"></script>
- run
npm run dev
- down load
Live server
- example/chose index -
go live
in VScode - see chrome's
source
orlog
ordebug
# 目录结构
benchmarks
性能、基准测试dist
打包输出flow
flow 语法类型声明 理解为约束接口吧哈哈packages
一些额外的包scripts
构建源码的文件夹build.js
构建入口
src
源码开始compiler
编译器core
核心 你要学的都在里面啦config.js
默认配置index.js
入口components
全局组件 keep-alivegloble-api
全局apiinstacne
vue实例开始observer
响应式原理util
工具方法vdom
虚拟dom和渲染和patch相关
platforms
构建后不同平台的入口server
服务器渲染相关
test
types
ts类型声明 对应一下flow
# flow
- 做静态类型检查
/* @flow */
.... code ....
--------------
flow 有完整的数据结构
├── compiler.js # 编译相关
├── component.js # 组件数据结构
├── global-api.js # Global API 结构
├── modules.js # 第三方库定义
├── options.js # 选项相关
├── ssr.js # 服务端渲染相关
├── vnode.js # 虚拟 node 相关
.flowconfig
[libs]
部分用来描述包含指定库定义的目录
# GlobalAPI
src/globalapi/
下的所有src/core/index.js
当这里是入口吧
import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
...
initGlobalAPI(Vue) //这里的vue从instence里来的
...
- 静态属性方法
src/globalapi/inde.js
initGlobalAPI
全局api方法... // 对config的处理 const configDef = {} configDef.get = () => config if (process.env.NODE_ENV !== 'production') { configDef.set = () => { warn( 'Do not replace the Vue.config object, set individual fields instead.' ) } } Object.defineProperty(Vue, 'config', configDef) //... Vue.set = set Vue.delete = del Vue.nextTick = nextTick //option Vue.options = Object.create(null) // 'component','directive','filter' ASSET_TYPES.forEach(type => { Vue.options[type + 's'] = Object.create(null) }) //还有一些绑定在component上的扩展, //<keep-alive> 组件见builtInComponents里 extend(Vue.options.components, builtInComponents) // initUse(Vue)//Vue.use = function (plugin: Function | Object) initMixin(Vue)// Vue.mixin = function (mixin: Object) initExtend(Vue)// Vue.extend = function (extendOptions: Object): Function initAssetRegisters(Vue) //ASSET_TYPES 'component','directive','filter'
builtInComponents
Vue.extend
子类构造器src/globalapi/extend.js
- 复习下怎么用
// 创建构造器 var Profile = Vue.extend({ template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>', data: function () { return { firstName: 'Walter', lastName: 'White', alias: 'Heisenberg' } } }) //---------------------- // 创建 Profile 实例,并挂载到一个元素上。 <div id="mount-point"></div> new Profile().$mount('##mount-point') // --------------------- // res <p>Walter White aka Heisenberg</p>
- 先创建一个类Sub,接着通过原型继承的方式将该类继承基础Vue类,然后给Sub类添加一些属性以及将父类的某些属性复制到Sub类上,最后将Sub类返回
Vue.extend = function (extendOptions: Object): Function { extendOptions = extendOptions || {} const Super = this // yiki: point to Class `Vue` const SuperId = Super.cid // yiki: unique identifier const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {}) // pool if (cachedCtors[SuperId]) { return cachedCtors[SuperId] } const name = extendOptions.name || Super.options.name if (process.env.NODE_ENV !== 'production' && name) { validateComponentName(name) // 校验 } // yiki: sub class 继承开始 const Sub = function VueComponent (options) { this._init(options) } Sub.prototype = Object.create(Super.prototype) Sub.prototype.constructor = Sub Sub.cid = cid++ // identifier Sub.options = mergeOptions( Super.options, extendOptions ) // 将父类保存到子类的super属性中,以确保在子类中能够拿到父类 Sub['super'] = Super // ---- 初始化props和computed if (Sub.options.props) { initProps(Sub) } if (Sub.options.computed) { initComputed(Sub) } // copy Sub.extend = Super.extend Sub.mixin = Super.mixin Sub.use = Super.use ASSET_TYPES.forEach(function (type) { Sub[type] = Super[type] }) if (name) { Sub.options.components[name] = Sub } // 给子类新增三个独有的属性 Sub.superOptions = Super.options Sub.extendOptions = extendOptions Sub.sealedOptions = extend({}, Sub.options) // yiki: When sub class is created , use Fater class's cid as key, then store to `cachedCtors` // cache constructor cachedCtors[SuperId] = Sub return Sub }