源码目录:
源码: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"}