Vue 核心原理精简
init 初始化Vue 原型上方法
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
Vue.prototype._init
Vue/VueComponent 构造函数调用的唯一方法
初始化Vue组件
initLifecycle(vm)
- while parent.$parent 绑定parent
- 初始化$parent, $children, $refs 变量
- 初始化$root 判断有没有parent , 没有就绑定到vm
initEvents(vm)
- TODO
updateListerner
callHook(vm, 'beforeCreate')
调用 beforeCreate生命周期
initState(vm)
- initProps(vm)
1. - initData(vm)
- 遍历$options.data
- vm._data = $data
- 如果是函数就执行 data.call(vm) 绑定到当前实例vm
- Object.keys 遍历 key
- 判断 prop 里面有没有key, 有key 就不绑定到 vm 上
proxy(vm, keys[i])
- Object.defineProperty 把 $data 里面所有属性绑定到 this 实例上
- set, get() 处理 vm._data 里面属性
observe(data)
- new Observer(data)
- 遍历$options.data
- initComputed(vm)
- initMethods(vm)
- initWatch(vm)
callHook(vm, 'created')
initRender(vm)
function initRender (vm: Component) {
// ***
vm._renderContext = vm.$options._parentVnode && vm.$options._parentVnode.context
vm.$slots = resolveSlots(vm.$options._renderChildren, vm._renderContext)
vm.$createElement = bind(createElement, vm)
if (vm.$options.el) {
vm.$mount(vm.$options.el) // 挂载元素到vue 实例上。开始执行渲染方法
}
}
vm.$mount == Vue.prototype._mount
Vue.prototype._mount
挂载元素
会调用 beforeMount mounted
callHook(vm, 'beforeMount')
vm._watcher = new Watcher(vm, () => { // 这件箭头回调函数回立即执行, expOrFun 这里会在Watcher 里最后一行的this.get() 中被调用
vm._update(vm._render(), hydrating) // _render 会调用 编译dom 字符串的js(里面如果使用到data里面的值,就会调用Object.defineProperty 里面的get 进行 `依赖收集` 。
}, noop)
lifecycleMixin 初始化一些的生命周期函数
Observer
constructor(value)
this.dep = new Dep()
判断value 为数组的话就, 绑定 arrayMethods vue 处理好重写push。。。等方法的数组的原型
observerArray 遍历数组, 给所有属性绑定observe
walk 处理所有非数组的值
-
defineReactive 遍历 obj[key]
- dep = new Dep()
defineProperty get
被使用的话,回进入到这里- 取值
- Dep.target 构造函数静态属性 target 有值的情况下 调用
dep.depend
方法 ,然后放在Dep.target.addDep(this)
(这里的Dep.target 通常是Watcher实例)
defineProperty set
- 取value 判断是否呵newVal相等, 如果相等就return
- 设置值value ; setter.call(obj, newVal)
observe(neVal)
重新监听新值- dep.notify()
Dep
subs: Array
; 依赖数组
depend () {
if (Dep.target) {
Dep.target.addDep(this) // 将当前dep 添加到Watcher 实例中
}
}
notify()
会处理当前实例的所有的subs (Watcher实例) .update()
方法
Watcher
通常 watch , $watch 会使用到这对象
constructor (
vm: Component, // 实例
expOrFn: string | Function, // mounted 之前会传函数过来
cb: Function, // 回调函数
options?: Object = {}
)
this.getter = expOrFn// 判断是否为函数如果为函数就直接复赋值,否则为String 调用`parsePath(expOrFn)` 再赋值为this.getter
this.value = this.lazy
? undefined
: this.get() // this.get() 会执行依赖收集的方法
get () {
pushTarget(this) // 将当成watcher 实例,赋值为Dep.target静态属性上
const value = this.getter.call(this.vm, this.vm) // (在mounted之前的expOrFn)执行这个方法会调用实例上的_render 方法,从而会渲染到dom,这样就回调用data 里面的 get 方法, 然后就会获取到Dep
if (this.deep) { // 深度监听vue
traverse(value)
}
popTarget() // 取消赋值到 Dep.target = null
this.cleanupDeps()
return value
}
addDep (dep: Dep) {
const id = dep.id
if (!this.newDepIds.has(id)) {
this.newDepIds.add(id)
this.newDeps.push(dep) //
if (!this.depIds.has(id)) {
dep.addSub(this) // Dep 对象添加当前 Watcher 实例
}
}
}
评论区