vue 2.0源码学习笔记—new Vue ( Vue 初始化过程 )
Posted 慢慢成长,每天进步一点点。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue 2.0源码学习笔记—new Vue ( Vue 初始化过程 )相关的知识,希望对你有一定的参考价值。
new Vue(Vue 初始化)
一个vue实例化到底经历了什么?已下是博主自己的总结,不正确的地方请指出,谢谢~
一、简述
new Vue 经历了
1. $slots
2. $scopedSlots
3. beforeCreate
4. inject
5. props
6. methods
7. data
8. computed
9. watch
10. provide
11. created
12. beforeMount
13. mounted
使用new Vue
使用 vue-cli创建(vue create 项目名称)项目,找到main.js文件
...
new Vue({
el: \'#app\',
router,
components: { App },
template: \'<App />\'
})
...
二、源码层面理解(vue源码)
1. 源码下载
前往git下载 [https://github.com/vuejs](vue-dev源码)
2. Vue 构造函数
文件位置:vue-dev/src/core/index.js
...
function Vue (options) {
...
this._init(options)
}
// 为Vue原型(Vue.prototype.)添加各种函数
initMixin(Vue) // 添加 _init 函数
stateMixin(Vue) // 添加 $data, $props, $set, $delete, $watch(expOrFn, cb, options)
eventsMixin(Vue) // 添加 $on, $once, $off, $emit 事件
lifecycleMixin(Vue) // 添加 _update, $forceUpdate, $destroy 函数
renderMixin(Vue) // 添加 $nextTick, _render 函数
export default Vue
其中关键的就是this._init(options),它由initMixin(Vue)添加到Vue对象的原型上,在new Vue的最后调用,传入options
3. _init函数
文件位置:vue-dev/src/core/instance/init.js
Vue.prototype._init = function (options?: Object) {
const vm: Component = this
// a uid
vm._uid = uid++
...
// merge options
if (options && options._isComponent) {
initInternalComponent(vm, options)
} else {
vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor), options || {}, vm)
}
...
vm._self = vm
initLifecycle(vm) // 初始化vm
initEvents(vm) // 初始化 _events(清空), _hasHookEvent, listeners
initRender(vm) /* 初始化 _vnode, _staticTrees, $slots, $scopedSlots, _c, $createElement
使用defineReactive定义 vm 响应式的 $attrs, $listeners*/
callHook(vm, \'beforeCreate\') // 调用beforeCreate钩子函数
initInjections(vm) // resolve injections before data/props
initState(vm) /* 依次初始化props, methods, data, computed, watch
initProps, initMethods, initData, initComputed, initWatch */
initProvide(vm) // resolve provide after data/props
callHook(vm, \'created\') // 调用created钩子函数
...
if (vm.$options.el) {
vm.$mount(vm.$options.el)
/*
1. callHook(vm, \'beforeMount\') // 调用beforeMount钩子函数
2. new Watcher(vm, updateComponent, noop, { // 添加updateComponent的观察者
before () {
if (vm._isMounted && !vm._isDestroyed) {
callHook(vm, \'beforeUpdate\') // 调用beforeUpdate钩子函数
}
}
}, true )
3. callHook(vm, \'mounted\') // 调用mounted钩子函数
*/
}
}
initState(vm)详解
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)
}
}
在initState中,完成了props, methods, data, computed, watch的挂载
以其中的initData为例:
function initData (vm: Component) {
let data = vm.$options.data
data = vm._data = typeof data === \'function\'
? getData(data, vm)
: data || {}
// 判断是否为对象 Object.prototype.toString.call(obj) === \'[object Object]\'
...
const keys = Object.keys(data)
const props = vm.$options.props
const methods = vm.$options.methods
let i = keys.length
while (i--) {
const key = keys[i]
...
proxy(vm, `_data`, key) // data中的属性代理到vm实例上去,这样就可以在vm实例中使用this.xx访问到data中的xx了
...
}
// observe data
observe(data, true /* asRootData */) // 为data添加观察者,这样修改就能触发更新
}
完~
以上是关于vue 2.0源码学习笔记—new Vue ( Vue 初始化过程 )的主要内容,如果未能解决你的问题,请参考以下文章
vue.js 2.0 官方文档学习笔记 —— 01. vue 介绍