mirror of https://github.com/vuejs/core.git
wip: render fallback nodes for empty vfor
This commit is contained in:
parent
e28b96bea8
commit
dd311402a9
|
@ -15,8 +15,10 @@ import { isArray, isObject, isString } from '@vue/shared'
|
|||
import { createComment, createTextNode } from './dom/node'
|
||||
import {
|
||||
type Block,
|
||||
ForFragment,
|
||||
VaporFragment,
|
||||
insert,
|
||||
remove,
|
||||
remove as removeBlock,
|
||||
} from './block'
|
||||
import { warn } from '@vue/runtime-dom'
|
||||
|
@ -77,7 +79,7 @@ export const createFor = (
|
|||
setup?: (_: {
|
||||
createSelector: (source: () => any) => (cb: () => void) => void
|
||||
}) => void,
|
||||
): VaporFragment => {
|
||||
): ForFragment => {
|
||||
const _insertionParent = insertionParent
|
||||
const _insertionAnchor = insertionAnchor
|
||||
if (isHydrating) {
|
||||
|
@ -94,7 +96,7 @@ export const createFor = (
|
|||
let currentKey: any
|
||||
// TODO handle this in hydration
|
||||
const parentAnchor = __DEV__ ? createComment('for') : createTextNode()
|
||||
const frag = new VaporFragment(oldBlocks)
|
||||
const frag = new ForFragment(oldBlocks)
|
||||
const instance = currentInstance!
|
||||
const canUseFastRemove = !!(flags & VaporVForFlags.FAST_REMOVE)
|
||||
const isComponent = !!(flags & VaporVForFlags.IS_COMPONENT)
|
||||
|
@ -123,6 +125,14 @@ export const createFor = (
|
|||
} else {
|
||||
parent = parent || parentAnchor!.parentNode
|
||||
if (!oldLength) {
|
||||
// remove fallback nodes if needed
|
||||
if (frag.fallback) {
|
||||
const fallbackNodes = frag.nodes[0] as any
|
||||
if (fallbackNodes) {
|
||||
remove(fallbackNodes, parent!)
|
||||
}
|
||||
}
|
||||
|
||||
// fast path for all new
|
||||
for (let i = 0; i < newLength; i++) {
|
||||
mount(source, i)
|
||||
|
@ -329,6 +339,11 @@ export const createFor = (
|
|||
frag.nodes.push(parentAnchor)
|
||||
}
|
||||
|
||||
// render fallback nodes if needed
|
||||
if (isMounted && frag.fallback && newLength === 0) {
|
||||
insert((frag.nodes[0] = frag.fallback()), parent!, parentAnchor)
|
||||
}
|
||||
|
||||
setActiveSub(prevSub)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,17 +18,24 @@ export type Block =
|
|||
|
||||
export type BlockFn = (...args: any[]) => Block
|
||||
|
||||
export class VaporFragment {
|
||||
nodes: Block
|
||||
export class VaporFragment<T extends Block = Block> {
|
||||
nodes: T
|
||||
anchor?: Node
|
||||
insert?: (parent: ParentNode, anchor: Node | null) => void
|
||||
remove?: (parent?: ParentNode) => void
|
||||
fallback?: BlockFn
|
||||
|
||||
constructor(nodes: Block) {
|
||||
constructor(nodes: T) {
|
||||
this.nodes = nodes
|
||||
}
|
||||
}
|
||||
|
||||
export class ForFragment extends VaporFragment<Block[]> {
|
||||
constructor(nodes: Block[]) {
|
||||
super(nodes)
|
||||
}
|
||||
}
|
||||
|
||||
export class DynamicFragment extends VaporFragment {
|
||||
anchor: Node
|
||||
scope: EffectScope | undefined
|
||||
|
@ -67,14 +74,16 @@ export class DynamicFragment extends VaporFragment {
|
|||
|
||||
if (this.fallback && !isValidBlock(this.nodes)) {
|
||||
parent && remove(this.nodes, parent)
|
||||
// handle nested dynamic fragment
|
||||
if (isFragment(this.nodes)) {
|
||||
renderFallback(this.nodes, this.fallback, key)
|
||||
} else {
|
||||
this.nodes =
|
||||
(this.scope || (this.scope = new EffectScope())).run(this.fallback) ||
|
||||
[]
|
||||
}
|
||||
const scope = this.scope || (this.scope = new EffectScope())
|
||||
scope.run(() => {
|
||||
// handle nested fragment
|
||||
if (isFragment(this.nodes)) {
|
||||
renderFallback(this.nodes, this.fallback!)
|
||||
} else {
|
||||
this.nodes = this.fallback!() || []
|
||||
}
|
||||
})
|
||||
|
||||
parent && insert(this.nodes, parent, this.anchor)
|
||||
}
|
||||
|
||||
|
@ -82,19 +91,21 @@ export class DynamicFragment extends VaporFragment {
|
|||
}
|
||||
}
|
||||
|
||||
function renderFallback(
|
||||
fragment: VaporFragment,
|
||||
fallback: BlockFn,
|
||||
key: any,
|
||||
): void {
|
||||
function renderFallback(fragment: VaporFragment, fallback: BlockFn): void {
|
||||
if (!fragment.fallback) fragment.fallback = fallback
|
||||
|
||||
if (fragment instanceof DynamicFragment) {
|
||||
const nodes = fragment.nodes
|
||||
if (isFragment(nodes)) {
|
||||
renderFallback(nodes, fallback, key)
|
||||
renderFallback(nodes, fallback)
|
||||
} else {
|
||||
if (!fragment.fallback) fragment.fallback = fallback
|
||||
fragment.update(fragment.fallback, key)
|
||||
fragment.update(fragment.fallback)
|
||||
}
|
||||
} else if (fragment instanceof ForFragment) {
|
||||
// TODO handle nested ForFragment
|
||||
fragment.nodes[0] = fallback() || []
|
||||
} else {
|
||||
// vdom slots
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue