perf: improve inject performance
This commit is contained in:
parent
0952d4cf51
commit
117630fb92
@ -7,24 +7,29 @@ export function provide<T>(key: Key<T>, value: T | Value<T>) {
|
|||||||
if (!currentInstance) {
|
if (!currentInstance) {
|
||||||
// TODO warn
|
// TODO warn
|
||||||
} else {
|
} else {
|
||||||
const provides = currentInstance.provides || (currentInstance.provides = {})
|
let provides = currentInstance.provides
|
||||||
|
// by default an instance inherits its parent's provides object
|
||||||
|
// but when it needs to provide values of its own, it creates its
|
||||||
|
// own provides object using parent provides object as prototype.
|
||||||
|
// this way in `inject` we can simply look up injections from direct
|
||||||
|
// parent and let the prototype chain do the work.
|
||||||
|
const parentProvides =
|
||||||
|
currentInstance.parent && currentInstance.parent.provides
|
||||||
|
if (parentProvides === provides) {
|
||||||
|
provides = currentInstance.provides = Object.create(parentProvides)
|
||||||
|
}
|
||||||
provides[key as any] = value
|
provides[key as any] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inject<T>(key: Key<T>): Value<T> | undefined {
|
export function inject<T>(key: Key<T>): Value<T> | undefined {
|
||||||
// traverse parent chain and look for provided value
|
|
||||||
if (!currentInstance) {
|
if (!currentInstance) {
|
||||||
// TODO warn
|
// TODO warn
|
||||||
} else {
|
} else {
|
||||||
let parent = currentInstance.parent
|
const provides = currentInstance.parent && currentInstance.provides
|
||||||
while (parent) {
|
if (provides) {
|
||||||
const { provides } = parent
|
const val = provides[key as any]
|
||||||
if (provides !== null && provides.hasOwnProperty(key as any)) {
|
return isValue(val) ? val : value(val)
|
||||||
const val = provides[key as any]
|
|
||||||
return isValue(val) ? val : value(val)
|
|
||||||
}
|
|
||||||
parent = parent.parent
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ export type ComponentInstance<P = Data, S = Data> = {
|
|||||||
update: ReactiveEffect
|
update: ReactiveEffect
|
||||||
render: RenderFunction<P, S> | null
|
render: RenderFunction<P, S> | null
|
||||||
effects: ReactiveEffect[] | null
|
effects: ReactiveEffect[] | null
|
||||||
provides: Data | null
|
provides: Data
|
||||||
|
|
||||||
// the rest are only for stateful components
|
// the rest are only for stateful components
|
||||||
data: S
|
data: S
|
||||||
@ -194,7 +194,7 @@ export function createComponentInstance(
|
|||||||
rtc: null,
|
rtc: null,
|
||||||
ec: null,
|
ec: null,
|
||||||
effects: null,
|
effects: null,
|
||||||
provides: null,
|
provides: parent ? parent.provides : {},
|
||||||
|
|
||||||
// public properties
|
// public properties
|
||||||
data: EMPTY_OBJ,
|
data: EMPTY_OBJ,
|
||||||
@ -225,7 +225,6 @@ export function setupStatefulComponent(instance: ComponentInstance) {
|
|||||||
// 2. call setup()
|
// 2. call setup()
|
||||||
const { setup } = Component
|
const { setup } = Component
|
||||||
if (setup) {
|
if (setup) {
|
||||||
currentInstance = instance
|
|
||||||
// the props proxy makes the props object passed to setup() reactive
|
// the props proxy makes the props object passed to setup() reactive
|
||||||
// so props change can be tracked by watchers
|
// so props change can be tracked by watchers
|
||||||
// it will be updated in resolveProps() on updates before render
|
// it will be updated in resolveProps() on updates before render
|
||||||
@ -234,7 +233,11 @@ export function setupStatefulComponent(instance: ComponentInstance) {
|
|||||||
: null)
|
: null)
|
||||||
const setupContext = (instance.setupContext =
|
const setupContext = (instance.setupContext =
|
||||||
setup.length > 1 ? createSetupContext(instance) : null)
|
setup.length > 1 ? createSetupContext(instance) : null)
|
||||||
|
|
||||||
|
currentInstance = instance
|
||||||
const setupResult = setup.call(null, propsProxy, setupContext)
|
const setupResult = setup.call(null, propsProxy, setupContext)
|
||||||
|
currentInstance = null
|
||||||
|
|
||||||
if (isFunction(setupResult)) {
|
if (isFunction(setupResult)) {
|
||||||
// setup returned an inline render function
|
// setup returned an inline render function
|
||||||
instance.render = setupResult
|
instance.render = setupResult
|
||||||
@ -247,7 +250,6 @@ export function setupStatefulComponent(instance: ComponentInstance) {
|
|||||||
}
|
}
|
||||||
instance.render = Component.render as RenderFunction
|
instance.render = Component.render as RenderFunction
|
||||||
}
|
}
|
||||||
currentInstance = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user