定义Vue
找到入口文件
首先在vue的源码中找到入口文件,package.json找到
"scripts": {
...
"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev",
...
}
这里指出是在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,然后找到alias.js文件
module.exports = {
...
web: resolve('src/platforms/web'),
...
}
那么完整的路径就是src/platforms/web/entry-runtime-with-compiler.js
entry-runtime-with-compiler.js
这个文件大致做了三件事:
- 定义
mount,指向了原型上的$mount方法,会在下一个$mount中调用 - 在Vue的原型上挂载了
$mount方法,负责找到render函数,再调用上边的mount方法 - 在Vue上挂载了
compile,负责把用户编写的render或者template编译成render函数
这里只是Vue的原型上挂载了一些方法,还不是Vue构造方法的地方
import Vue from './runtime/index'
runtime/index.js
// patch就是将vnode渲染成dom,diff就在这里面
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)
}
从这个文件可以看到
import Vue from 'core/index'
这里的Vue又是从core文件引用的,initGlobalAPI又对Vue做了处理
import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
...
initGlobalAPI(Vue)
...
export default Vue
global-api/index
export function initGlobalAPI (Vue: GlobalAPI) {
...
Vue.util = {
warn,
extend,
mergeOptions,
defineReactive
}
// 这里的set、del和后面用到的$set、$del是一样的
Vue.set = set
Vue.delete = del
Vue.nextTick = nextTick
// 这里就是为什么调用observable方法处理数据,可以让数据响应式
Vue.observable = <T>(obj: T): T => {
observe(obj)
return obj
}
...
// 定义plugin要用的api
initUse(Vue)
// merge操作
initMixin(Vue)
// 定义Vue.extend
initExtend(Vue)
// 给options添加了component、directive、filter
initAssetRegisters(Vue)
}
use方法就是为plugin提供的api,Vue.use(plugin),就是调用的这里
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) {
...
// 这里的this指向当前的Vue实例,添加到数组的最前头
const args = toArray(arguments, 1)
args.unshift(this)
// plugin可以是对象也可以是函数,在这里可以看到plugin接收到的第一个参数就是Vue的原型
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
installedPlugins.push(plugin)
return this
}
}
instance/index
这里定义了最初是的Vue构造方法,基本上就是在原型上挂载各种方法
function Vue (options) {
...
this._init(options)
}
// 在原型上挂载_init,就是new Vue时调用的
initMixin(Vue)
// 拦截了$data、$props,对其访问就是访问了this._data、this._props,又在原型上挂载了$watch
stateMixin(Vue)
// 在原型上挂载$on、$emit等方法
eventsMixin(Vue)
// 在原型上挂载_update、$foceUpdate、$destory
lifecycleMixin(Vue)
// 在原型上挂载$nextTick、_render
renderMixin(Vue)
以上就是在new Vue()之前要执行的方法 源码调试地址