createApp({}).mount(‘#app’)
入口文件 runtime-dom/src/index.tx
- createApp -> createRenderer -> createBaseRenderer(这里还创建了render函数以及一系列渲染时的函数) -> createAppAPI(返回了真正的createApp方法),返回了 实例 app,
- 然后 app.mount(“#app”) -> createVNode -> render(vnode,rootcontainier,isSVG) -> patch -> processComponent -> mountComponent(初次渲染)或者是updateComponent ->(createComponentInstance , setupComponent,setupRenderEffect)
- 对于setupComponent,有setup函数和没有setup函数分情况处理,如果有就走setup函数处理,初始化props等需要传递给setup函数的参数,调用setup,setupComponent->finishComponentSetup(在这里会处理 2.x版本的options选项初始化),
- 对于setupRenderEffect,执行一系列生命钩子函数,创建渲染ReactiveEffect,并执行了**effect.run()**方法
ReactiveEffect
类似于 vue2.x 的Watcher, computed,watch,渲染过程中componentUpdateFn也使用了 ReactiveEffect,
const effect = new ReactiveEffect(fn,…)后,除了计算属性会在被访问时才去调用effect.run()->调用fn(),在fn里访问响应式变量,收集依赖,其余的setupRenderEffect,watch,watchEffect,均会在创建ReactiveEffect后调用effect.run()收集依赖,其中
- setupRenderEffect会访问依赖的响应变量
- watch(source,cb,options),会执行访问source的函数,收集依赖
- watchEffect(fn),会自动执行一次fn收集依赖
- effect(fn,options),其中options有个lazy:true选项,表示不立即执行fn函数收集依赖,返回一个run函数,再次调用run(),执行一次fn函数,收集依赖
// 1.计算属性
// computed.ts
// ComputedRefImpl类构造函数调用了new ReactiveEffect
this.effect = new ReactiveEffect(getter, () => {
if (!this._dirty) {
this._dirty = true
triggerRefValue(this)
}
})
// 2. effect
// effect.ts
// effect函数中,可以接收第二个参数effect(fn,{lazy:true}),表示不立即执行
const _effect = new ReactiveEffect(fn)
// 3. apiWatch.ts doWatch方法
// watch和watchEffect都是通过doWatch函数来,在这里调用new ReactiveEffect,然后根据不同情况执行effect.run(),对于watchEffect就是//执行器回调,对于watch就是访问监听的数据,然后收集依赖
const effect = new ReactiveEffect(getter, scheduler)
// 4. render.ts
//在 setupRenderEffect中
const effect = (instance.effect = new ReactiveEffect(
componentUpdateFn,//更新组件函数
() => queueJob(update),
instance.scope // track it in component's effect scope
))