refactor: remove unnecessary functional wrapper + delay for async components
This commit is contained in:
parent
2c753388c3
commit
9e62c3bd9a
@ -1,10 +1,10 @@
|
|||||||
import { Slots, VNodeData } from './vdom'
|
import { Slots } from './vdom'
|
||||||
import { MountedComponent } from './component'
|
import { MountedComponent } from './component'
|
||||||
|
|
||||||
export type Data = Record<string, any>
|
export type Data = Record<string, any>
|
||||||
|
|
||||||
export interface RenderFunction<P = Data> {
|
export interface RenderFunction<P = Data> {
|
||||||
(props: P, slots: Slots, attrs: Data, rawData: VNodeData | null): any
|
(props: P, slots: Slots, attrs: Data): any
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComponentOptions<D = Data, P = Data> {
|
export interface ComponentOptions<D = Data, P = Data> {
|
||||||
|
@ -284,7 +284,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
const render = tag as FunctionalComponent
|
const render = tag as FunctionalComponent
|
||||||
const { props, attrs } = resolveProps(data, render.props, render)
|
const { props, attrs } = resolveProps(data, render.props, render)
|
||||||
const subTree = (vnode.children = normalizeComponentRoot(
|
const subTree = (vnode.children = normalizeComponentRoot(
|
||||||
render(props, slots || EMPTY_OBJ, attrs || EMPTY_OBJ, data),
|
render(props, slots || EMPTY_OBJ, attrs || EMPTY_OBJ),
|
||||||
vnode,
|
vnode,
|
||||||
attrs,
|
attrs,
|
||||||
render.inheritAttrs
|
render.inheritAttrs
|
||||||
@ -581,7 +581,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
if (shouldUpdate) {
|
if (shouldUpdate) {
|
||||||
const { props, attrs } = resolveProps(nextData, render.props, render)
|
const { props, attrs } = resolveProps(nextData, render.props, render)
|
||||||
const nextTree = (nextVNode.children = normalizeComponentRoot(
|
const nextTree = (nextVNode.children = normalizeComponentRoot(
|
||||||
render(props, nextSlots || EMPTY_OBJ, attrs || EMPTY_OBJ, nextData),
|
render(props, nextSlots || EMPTY_OBJ, attrs || EMPTY_OBJ),
|
||||||
nextVNode,
|
nextVNode,
|
||||||
attrs,
|
attrs,
|
||||||
render.inheritAttrs
|
render.inheritAttrs
|
||||||
@ -1167,6 +1167,10 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
(__COMPAT__ && (parentVNode.children as MountedComponent)) ||
|
(__COMPAT__ && (parentVNode.children as MountedComponent)) ||
|
||||||
createComponentInstance(parentVNode, Component, parentComponent)
|
createComponentInstance(parentVNode, Component, parentComponent)
|
||||||
|
|
||||||
|
if (instance.beforeMount) {
|
||||||
|
instance.beforeMount.call(instance.$proxy)
|
||||||
|
}
|
||||||
|
|
||||||
const queueUpdate = (instance.$forceUpdate = () => {
|
const queueUpdate = (instance.$forceUpdate = () => {
|
||||||
queueJob(instance._updateHandle, flushHooks)
|
queueJob(instance._updateHandle, flushHooks)
|
||||||
})
|
})
|
||||||
@ -1206,9 +1210,6 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
instance: MountedComponent,
|
instance: MountedComponent,
|
||||||
ref: Ref | null
|
ref: Ref | null
|
||||||
) {
|
) {
|
||||||
if (instance.beforeMount) {
|
|
||||||
instance.beforeMount.call(instance.$proxy)
|
|
||||||
}
|
|
||||||
if (ref) {
|
if (ref) {
|
||||||
mountRef(ref, instance)
|
mountRef(ref, instance)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ChildrenFlags } from '../flags'
|
import { ChildrenFlags } from '../flags'
|
||||||
import { createComponentVNode, VNodeData } from '../vdom'
|
import { createComponentVNode, Slots } from '../vdom'
|
||||||
import { Component, ComponentType, FunctionalComponent } from '../component'
|
import { Component, ComponentType, ComponentClass } from '../component'
|
||||||
|
|
||||||
export interface AsyncComponentFactory {
|
export interface AsyncComponentFactory {
|
||||||
(): Promise<ComponentType>
|
(): Promise<ComponentType>
|
||||||
@ -22,28 +22,37 @@ export type AsyncComponentOptions =
|
|||||||
interface AsyncContainerData {
|
interface AsyncContainerData {
|
||||||
comp: ComponentType | null
|
comp: ComponentType | null
|
||||||
err: Error | null
|
err: Error | null
|
||||||
|
delayed: boolean
|
||||||
timedOut: boolean
|
timedOut: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AsyncContainerProps {
|
export function createAsyncComponent(
|
||||||
options: AsyncComponentFullOptions
|
options: AsyncComponentOptions
|
||||||
rawData: VNodeData | null
|
): ComponentClass {
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
options = { factory: options }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AsyncContainer extends Component<
|
const {
|
||||||
AsyncContainerData,
|
factory,
|
||||||
AsyncContainerProps
|
timeout,
|
||||||
> {
|
delay = 200,
|
||||||
|
loading: loadingComp,
|
||||||
|
error: errorComp
|
||||||
|
} = options
|
||||||
|
|
||||||
|
return class AsyncContainer extends Component<AsyncContainerData> {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
comp: null,
|
comp: null,
|
||||||
err: null,
|
err: null,
|
||||||
|
delayed: false,
|
||||||
timedOut: false
|
timedOut: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
created() {
|
// doing this in beforeMount so this is non-SSR only
|
||||||
const { factory, timeout } = this.$props.options
|
beforeMount() {
|
||||||
if (factory.resolved) {
|
if (factory.resolved) {
|
||||||
this.comp = factory.resolved
|
this.comp = factory.resolved
|
||||||
} else {
|
} else {
|
||||||
@ -60,14 +69,18 @@ export class AsyncContainer extends Component<
|
|||||||
this.timedOut = true
|
this.timedOut = true
|
||||||
}, timeout)
|
}, timeout)
|
||||||
}
|
}
|
||||||
|
if (delay != null) {
|
||||||
|
this.delayed = true
|
||||||
|
setTimeout(() => {
|
||||||
|
this.delayed = false
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render(props: AsyncContainerProps) {
|
render(props: any, slots: Slots) {
|
||||||
if (this.err || (this.timedOut && !this.comp)) {
|
if (this.err || (this.timedOut && !this.comp)) {
|
||||||
const error =
|
const error =
|
||||||
this.err ||
|
this.err || new Error(`Async component timed out after ${timeout}ms.`)
|
||||||
new Error(`Async component timed out after ${props.options.timeout}ms.`)
|
|
||||||
const errorComp = props.options.error
|
|
||||||
return errorComp
|
return errorComp
|
||||||
? createComponentVNode(
|
? createComponentVNode(
|
||||||
errorComp,
|
errorComp,
|
||||||
@ -79,13 +92,12 @@ export class AsyncContainer extends Component<
|
|||||||
} else if (this.comp) {
|
} else if (this.comp) {
|
||||||
return createComponentVNode(
|
return createComponentVNode(
|
||||||
this.comp,
|
this.comp,
|
||||||
props.rawData,
|
props,
|
||||||
null,
|
slots,
|
||||||
ChildrenFlags.UNKNOWN_CHILDREN
|
ChildrenFlags.STABLE_SLOTS
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
const loadingComp = props.options.loading
|
return loadingComp && !this.delayed
|
||||||
return loadingComp
|
|
||||||
? createComponentVNode(
|
? createComponentVNode(
|
||||||
loadingComp,
|
loadingComp,
|
||||||
null,
|
null,
|
||||||
@ -95,19 +107,5 @@ export class AsyncContainer extends Component<
|
|||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} as ComponentClass
|
||||||
|
|
||||||
export function createAsyncComponent(
|
|
||||||
options: AsyncComponentOptions
|
|
||||||
): FunctionalComponent {
|
|
||||||
if (typeof options === 'function') {
|
|
||||||
options = { factory: options }
|
|
||||||
}
|
|
||||||
return (_, __, ___, rawData) =>
|
|
||||||
createComponentVNode(
|
|
||||||
AsyncContainer,
|
|
||||||
{ options, rawData },
|
|
||||||
null,
|
|
||||||
ChildrenFlags.NO_CHILDREN
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ export function createElementVNode(
|
|||||||
export function createComponentVNode(
|
export function createComponentVNode(
|
||||||
comp: any,
|
comp: any,
|
||||||
data: VNodeData | null,
|
data: VNodeData | null,
|
||||||
children: VNodeChildren,
|
children: VNodeChildren | Slots,
|
||||||
childFlags: ChildrenFlags,
|
childFlags: ChildrenFlags,
|
||||||
key?: Key | null,
|
key?: Key | null,
|
||||||
ref?: Ref | null
|
ref?: Ref | null
|
||||||
@ -169,7 +169,9 @@ export function createComponentVNode(
|
|||||||
|
|
||||||
// slots
|
// slots
|
||||||
let slots: any
|
let slots: any
|
||||||
if (childFlags === ChildrenFlags.UNKNOWN_CHILDREN) {
|
if (childFlags === ChildrenFlags.STABLE_SLOTS) {
|
||||||
|
slots = children
|
||||||
|
} else if (childFlags === ChildrenFlags.UNKNOWN_CHILDREN) {
|
||||||
childFlags = children
|
childFlags = children
|
||||||
? ChildrenFlags.DYNAMIC_SLOTS
|
? ChildrenFlags.DYNAMIC_SLOTS
|
||||||
: ChildrenFlags.NO_CHILDREN
|
: ChildrenFlags.NO_CHILDREN
|
||||||
@ -361,9 +363,12 @@ export function normalizeVNodes(
|
|||||||
|
|
||||||
// ensure all slot functions return Arrays
|
// ensure all slot functions return Arrays
|
||||||
function normalizeSlots(slots: { [name: string]: any }): Slots {
|
function normalizeSlots(slots: { [name: string]: any }): Slots {
|
||||||
const normalized: Slots = {}
|
if (slots._normalized) {
|
||||||
|
return slots
|
||||||
|
}
|
||||||
|
const normalized = { _normalized: true } as any
|
||||||
for (const name in slots) {
|
for (const name in slots) {
|
||||||
normalized[name] = (...args) => normalizeSlot(slots[name](...args))
|
normalized[name] = (...args: any[]) => normalizeSlot(slots[name](...args))
|
||||||
}
|
}
|
||||||
return normalized
|
return normalized
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user