源碼目錄:
源碼:src / core / instance / index.js
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/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
從這一段代碼可以看出, Vue就是一個普通的函數(構造函數),傳入了一個 options 參數, 這個參數是一些用戶傳入的配置信息, 關鍵看 this._init(options) 這個方法, 這個方法就是初始化一些Vue的配置, 接着找 這個 _init() 方法,
src/ core / instance/ init.js line:15
export function initMixin (Vue: Class<Component>) {
Vue.prototype._init = function (options?: Object) {
const vm: Component = 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
// 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 {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
}
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
initProxy(vm)
} else {
vm._renderProxy = vm
}
// expose real self
vm._self = vm
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
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)
}
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
}
可以看到在函數 Vue 的原型上擴展了一個 _init() 方法, 這裏邊的代碼看這些,可以看出,這個方法,就是初始化Vue 的一些基礎內部配置,以及最後的掛載到 指定的 dom 上
這裏可以看出初始化了
組件生命週期鉤子,自定義事件, 渲染, 以及 state 狀態 等
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
接着看
src/core /instance/state.js (代碼太多就截圖了),
這裏接着初始了,
數據data, 屬性Props,觀測 Watch,計算屬性Computed, 以及methods方法,混入等
總結:
new Vue() 發生了:
從Vue來說, 就是Vue內部初始化了一些配置,
那麼從new 的層面上講,就是
模擬一個 new 的 實現
function Animal(name) {
this.name = name
return {
name: 'liSi'
}
}
Animal.prototype.say = function() {
console.log('Miao')
}
function myNew() {
// 取出第一個參數, 剩餘的arguments 就是其他的參數
let constructor = [].shift.call(arguments)
// 不要使用 Object.create(null) 創建的對象, 因爲沒有原型鏈 __proto__
let obj = {} // 返回的結果
obj.__proto__ = constructor.prototype // 繼承原型上的方法
let result = constructor.apply(obj, arguments) // 改變this 指向 ,把剩餘的參數傳給它
// 判斷如果是一個 引用類型, 則直接返回這個引用類型的數據
// 即判斷是不是 Object 的實例
return result instanceof Object ? result : obj
}
let animal = myNew(Animal, '貓')
console.log(animal) // {name: "liSi"}