拉取 vuejs v2.6.2 版本,安装好依赖之后,查看 package.json 文件 script 属性下的 dev 命令:
"dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web-full-dev"
这个脚本就是构建 vuejs 全代码(模版编译器 + runtime)的开发版本,打开 scripts/config.js 文件,搜索 web-full-dev,可看到:
// 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,这个文件主要是扩展了 Vue.prototype.$mount 方法,将 template 或者 el 编译为 render 函数,以下为核心代码:
import Vue from './runtime/index'
// 扩展$mount方法
const mount = Vue.prototype.$mount
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?: boolean
): Component {
el = el && query(el)
const options = this.$options
// 将template或者el属性转化为reder function
if (!options.render) {
let template = options.template
if (template) {
// 一些特殊处理
} else if (el) {
// el参数转为template
template = getOuterHTML(el)
}
// 如果有template就转为render函数挂在options上
if (template) {
const { render, staticRenderFns } = compileToFunctions(template, {
outputSourceRange: process.env.NODE_ENV !== 'production',
shouldDecodeNewlines,
shouldDecodeNewlinesForHref,
delimiters: options.delimiters,
comments: options.comments
}, this)
options.render = render
options.staticRenderFns = staticRenderFns
}
}
return mount.call(this, el, hydrating)
}
继续看,上述文件里的 Vue 是引用自./runtime/index 文件,查看该文件,核心代码如下:
import Vue from 'core/index'
import { mountComponent } from 'core/instance/lifecycle'
import { patch } from './patch'
import platformDirectives from './directives/index'
import platformComponents from './components/index'
// 加入内置v-model,v-show指令
extend(Vue.options.directives, platformDirectives)
// 加入内置的keep-alive,transition[-group]组件
extend(Vue.options.components, platformComponents)
// vnode对比方法,边对比边替换dom
Vue.prototype.__patch__ = inBrowser ? patch : noop
// 定义$mount方法
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 是引用自 core/index 文件,查看该文件,核心代码:
// 此处就是Vue的构造函数定义的文件
import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
// 从名字可以看出,该方法是添加Vue的全局api(文档中全局api中的所有api都在这里定义)
// Vue.extend/nextTick/set/delete/directive/filter/component/use/mixin/compile/observable/version
initGlobalAPI(Vue)
export default Vue
看下 Vue 构造函数的文件./instance/index:
import { initMixin } from "./init";
import { stateMixin } from "./state";
import { renderMixin } from "./render";
import { eventsMixin } from "./events";
import { lifecycleMixin } from "./lifecycle";
function Vue(options) {
this._init(options);
}
// 定义Vue.prototype._init方法
initMixin(Vue);
// 初始化Vue实例的一些属性或方法:vm.$props/$data/$set/$delete/$watch
stateMixin(Vue);
// 初始化Vue实例的事件方法:vm.$on/$emit/$off/$once
eventsMixin(Vue);
// 初始化Vue实例的生命周期相关的方法:vm._update/$forceUpdate/$destory
lifecycleMixin(Vue);
// 初始化Vue实例的渲染相关的方法:vm._render/$nextTick
renderMixin(Vue);
export default Vue;
至此整个 Vue 代码初始执行过程已经结束了,总结一下主要就是给 Vue 及 Vue.prototype 添加了很多属性和方法。