实例讲解vue源码架构


Posted in Javascript onJanuary 24, 2019

下载

去github上下载Vue https://github.com/vuejs/vue

npm install 
npm run dev

运行起来

rollup + flow

vue使用使用rollup打包,flow规范数据类型

rollup可以先用webpack套用,读起来差不多,时间有限,毕竟只有5分钟,这个就不用去看rollup文档了

入口

打开package.json

我们看scripts配置

"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev",
 "dev:cjs": "rollup -w -c scripts/config.js --environment TARGET:web-runtime-cjs-dev",

找到scripts/config.js

打开

根据配置TARGET的不同会选择不同的config

同时在这里配置了process.env.NODE_ENV 环境

TARGET有CommonJS,ES Modules,UMD关于js引入类型的

还有weex,ssr

'web-runtime-cjs-dev': {
  entry: resolve('web/entry-runtime.js'),
  dest: resolve('dist/vue.runtime.common.dev.js'),
  format: 'cjs',
  env: 'development',
  banner
 }

在alias.js下设置了别名路径

我们先介绍src/platforms

里面有web和weex 分别的web和weex入口

在web文件下是CommonJS,ES Modules,UMD关于js引入类型,server的打包入口

打开web/entry-runtime.js

引入

import Vue from './runtime/index'
export default Vue

打开./runtime/index

import Vue from 'core/index'
 
Vue.prototype.$mount = function (
 el?: string | Element,
 hydrating?: boolean
): Component {
 el = el && inBrowser ? query(el) : undefined
 return mountComponent(this, el, hydrating)
}
export default Vue

在vue原型上添加了mount方法

处理了devtools,没有安装提醒安装devtools

给了这句提示dev环境提示

You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html

platforms目录夹讲解完毕

core目录

打开core/instance/index

映入眼前的是

function Vue (options) {
 if (process.env.NODE_ENV !== 'production' &&
  !(this instanceof Vue)
 ) {
  warn('Vue is a constructor and should be called with the `new` keyword')
 }
 this._init(options)
}
 
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
 
export default Vue

先执行的是initMixin(Vue)

打开init

export function initMixin (Vue) {
 Vue.prototype._init = function (options?: Object) {
  const vm = this
  // a uid 
  vm._uid = uid++
   
  let startTag, endTag
  /* istanbul ignore if */
  if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
   startTag = `vue-perf-start:${vm._uid}`
   endTag = `vue-perf-end:${vm._uid}`
   mark(startTag)
  }
 
  // a flag to avoid this being observed
  vm._isVue = true
  // 处理传入的options
  // merge options
  if (options && options._isComponent) {
   // optimize internal component instantiation
   // since dynamic options merging is pretty slow, and none of the
   // internal component options needs special treatment.
   initInternalComponent(vm, options)
  } else {
    // 传入的options,默认的options一起合并挂载到vm.$options上
   vm.$options = mergeOptions(
    resolveConstructorOptions(vm.constructor),
    options || {},
    vm
   )
  }
  /* istanbul ignore else */
  if (process.env.NODE_ENV !== 'production') {
   // 代理
   initProxy(vm)
  } else {
   vm._renderProxy = vm
  }
  // 生命周期
  initLifecycle(vm)
   // emit on 事件
  initEvents(vm)
  // 处理render vdom
  initRender(vm)
  callHook(vm, 'beforeCreate')
  // 处理Injections
  initInjections(vm) // resolve injections before data/props
  // 双向数据绑定,监听订阅
  initState(vm)
  initProvide(vm) // resolve provide after data/props
  callHook(vm, 'created')
   
  /* istanbul ignore if */
  if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
   vm._name = formatComponentName(vm, false)
   mark(endTag)
   measure(`vue ${vm._name} init`, startTag, endTag)
  }
  // 渲染到dom
  if (vm.$options.el) {
   vm.$mount(vm.$options.el)
  }
 }
}

lifecycle

打开 lifecycle

export function callHook (vm: Component, hook: string) {
 // disable dep collection when invoking lifecycle hooks
 pushTarget()
 //执行对象的周期函数,周期函数最后被处理成数组
 const handlers = vm.$options[hook]
 const info = `${hook} hook`
 if (handlers) {
  for (let i = 0, j = handlers.length; i < j; i++) {
   invokeWithErrorHandling(handlers[i], vm, null, vm, info)
  }
 }
 if (vm._hasHookEvent) {
  vm.$emit('hook:' + hook)
 }
 popTarget()

callHook 的时候,是执行相应周期,开发者在周期函数里所写的

Events

initEvents实现了 emit on 等方法,请参考监听者订阅者模式,这里不详解

render
renderMixin函数
添加了 $nextTick _render 原型对象

$nextTick会在dom跟新后立即调用

nextTick(fn, this)是一个自执行函数

_render返回的是node的js数据,还不是dom

做了Vdom

initRender函数
给vm添加了_c和 $createElement用来渲染的方法

state

if (!(key in vm)) {
   proxy(vm, `_props`, key)
  }

给vue属性做代理,访问this.a可以得到this.data.a 的值

export function initState (vm: Component) {
 vm._watchers = []
 const opts = vm.$options
 if (opts.props) initProps(vm, opts.props)
 if (opts.methods) initMethods(vm, opts.methods)
 if (opts.data) {
  initData(vm)
 } else {
  observe(vm._data = {}, true /* asRootData */)
 }
 if (opts.computed) initComputed(vm, opts.computed)
 if (opts.watch && opts.watch !== nativeWatch) {
  initWatch(vm, opts.watch)
 }
}

给数据做监听

stateMixin函数

添加原型对象

Vue.prototype.$set = set
Vue.prototype.$delete = del

其他

src/compiler 做了编译处理

core/componetd 做了keep-alive

core/util 封装了通用方法

core/vdom vdom算法

以上整体架构分析完毕

实例讲解vue源码架构

Javascript 相关文章推荐
javascript 动态调整图片尺寸实现代码
Dec 28 Javascript
js中关于new Object时传参的一些细节分析
Mar 13 Javascript
用jQuery中的ajax分页实现代码
Sep 20 Javascript
JS画5角星方法介绍
Sep 17 Javascript
jQuery 2.0.3 源码分析之core(一)整体架构
May 27 Javascript
jquery实现的省市区三级联动
Apr 02 Javascript
详解A标签中href=&quot;&quot;的几种用法
Aug 20 Javascript
跨域解决之JSONP和CORS的详细介绍
Nov 21 Javascript
Vue指令v-for遍历输出JavaScript数组及json对象的常见方式小结
Feb 11 Javascript
微信小程序bindinput与bindsubmit的区别实例分析
Apr 17 Javascript
JavaScript遍历查找数组中最大值与最小值的方法示例
May 24 Javascript
HTML+JS实现“代码雨”效果源码(黑客帝国文字下落效果)
Mar 17 Javascript
详解Node.js amqplib 连接 Rabbit MQ最佳实践
Jan 24 #Javascript
JavaScript私有变量实例详解
Jan 24 #Javascript
小程序从手动埋点到自动埋点的实现方法
Jan 24 #Javascript
JavaScript递归函数定义与用法实例分析
Jan 24 #Javascript
jQuery实现当拉动滚动条到底部加载数据的方法分析
Jan 24 #jQuery
vue结合element-ui使用示例
Jan 24 #Javascript
VUE+Element环境搭建与安装的方法步骤
Jan 24 #Javascript
You might like
当海贼王变成JOJO风
2020/03/02 日漫
php数组函数序列之array_key_exists() - 查找数组键名是否存在
2011/10/29 PHP
基于PHP技术开发客服工单系统
2016/01/06 PHP
PHP Ajax跨域问题解决方案代码实例
2020/08/01 PHP
jQuery EasyUI API 中文文档 - TreeGrid 树表格使用介绍
2011/11/21 Javascript
jQuery 实时保存页面动态添加的数据的示例
2017/08/14 jQuery
jQuery实现手机号正则验证输入及自动填充空格功能
2018/01/02 jQuery
bmob js-sdk 在vue中的使用教程
2018/01/21 Javascript
Vue中computed与methods的区别详解
2018/03/24 Javascript
玩转Koa之koa-router原理解析
2018/12/29 Javascript
vue2配置scss的方法步骤
2019/06/06 Javascript
为vue项目自动设置请求状态的配置方法
2019/06/09 Javascript
vue-quill-editor 自定义工具栏和自定义图片上传路径操作
2020/08/03 Javascript
vue点击按钮实现简单页面的切换
2020/09/08 Javascript
解决vue项目axios每次请求session不一致的问题
2020/10/24 Javascript
微信小程序开发数据缓存基础知识辨析及运用实例详解
2020/11/06 Javascript
利用python批量检查网站的可用性
2016/09/09 Python
Python多进程multiprocessing用法实例分析
2017/08/18 Python
Python学习笔记之图片人脸检测识别实例教程
2019/03/06 Python
使用python进行广告点击率的预测的实现
2019/07/04 Python
Django 外键的使用方法详解
2019/07/19 Python
python__new__内置静态方法使用解析
2020/01/07 Python
PyQt5高级界面控件之QTableWidget的具体使用方法
2020/02/23 Python
Django数据库操作之save与update的使用
2020/04/01 Python
基于python实现MQTT发布订阅过程原理解析
2020/07/27 Python
python 牛顿法实现逻辑回归(Logistic Regression)
2020/10/15 Python
受外贸欢迎的美国主机:BlueHost
2017/05/16 全球购物
美国按摩椅批发网站:Titan Chair
2018/12/27 全球购物
生物化工工艺专业应届生求职信
2013/10/08 职场文书
平面设计岗位职责
2013/12/14 职场文书
护理专业自我鉴定
2014/01/30 职场文书
学生打架检讨书
2014/02/14 职场文书
党支部创先争优活动总结
2014/08/28 职场文书
2014市府办领导班子“四风问题”对照检查材料思想汇报
2014/09/24 职场文书
干部四风问题整改措施思想汇报
2014/10/13 职场文书
详解Python中下划线的5种含义
2021/07/15 Python