mirror of https://github.com/vuejs/core.git
wip: fix teleport root component hmr reload
This commit is contained in:
parent
b6468562e6
commit
b474ce0a1e
|
@ -317,7 +317,7 @@ describe('renderer: VaporTeleport', () => {
|
|||
expect(target.innerHTML).toBe('')
|
||||
})
|
||||
|
||||
test.todo('reload child + toggle disabled', async () => {
|
||||
test('reload child + toggle disabled', async () => {
|
||||
const target = document.createElement('div')
|
||||
const root = document.createElement('div')
|
||||
const childId = 'test3-child'
|
||||
|
@ -410,8 +410,6 @@ describe('renderer: VaporTeleport', () => {
|
|||
)
|
||||
expect(target.innerHTML).toBe('')
|
||||
|
||||
//bug: child reload not update teleport fragment's nodes
|
||||
|
||||
// toggle disabled
|
||||
disabled.value = false
|
||||
await nextTick()
|
||||
|
|
|
@ -25,6 +25,7 @@ export class VaporFragment {
|
|||
anchor?: Node
|
||||
insert?: (parent: ParentNode, anchor: Node | null) => void
|
||||
remove?: (parent?: ParentNode) => void
|
||||
getNodes?: () => Block
|
||||
|
||||
constructor(nodes: Block) {
|
||||
this.nodes = nodes
|
||||
|
@ -184,8 +185,8 @@ export function normalizeBlock(block: Block): Node[] {
|
|||
} else if (isVaporComponent(block)) {
|
||||
nodes.push(...normalizeBlock(block.block!))
|
||||
} else {
|
||||
if ((block as any).getNodes) {
|
||||
nodes.push(...normalizeBlock((block as any).getNodes()))
|
||||
if (block.getNodes) {
|
||||
nodes.push(...normalizeBlock(block.getNodes()))
|
||||
} else {
|
||||
nodes.push(...normalizeBlock(block.nodes))
|
||||
}
|
||||
|
|
|
@ -60,7 +60,11 @@ import {
|
|||
import { hmrReload, hmrRerender } from './hmr'
|
||||
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
||||
import { insertionAnchor, insertionParent } from './insertionState'
|
||||
import type { VaporTeleportImpl } from './components/Teleport'
|
||||
import {
|
||||
type VaporTeleportImpl,
|
||||
instanceToTeleportMap,
|
||||
teleportStack,
|
||||
} from './components/Teleport'
|
||||
|
||||
export { currentInstance } from '@vue/runtime-dom'
|
||||
|
||||
|
@ -209,6 +213,11 @@ export function createComponent(
|
|||
)
|
||||
|
||||
if (__DEV__) {
|
||||
let teleport = teleportStack[teleportStack.length - 1]
|
||||
if (teleport) {
|
||||
instanceToTeleportMap.set(instance, teleport)
|
||||
}
|
||||
|
||||
pushWarningContext(instance)
|
||||
startMeasure(instance, `init`)
|
||||
|
||||
|
@ -296,7 +305,7 @@ export function createComponent(
|
|||
onScopeDispose(() => unmountComponent(instance), true)
|
||||
|
||||
if (!isHydrating && _insertionParent) {
|
||||
insert(instance.block, _insertionParent, _insertionAnchor)
|
||||
mountComponent(instance, _insertionParent, _insertionAnchor)
|
||||
}
|
||||
|
||||
return instance
|
||||
|
|
|
@ -15,12 +15,45 @@ import {
|
|||
remove,
|
||||
} from '../block'
|
||||
import { createComment, createTextNode, querySelector } from '../dom/node'
|
||||
import type { LooseRawProps, LooseRawSlots } from '../component'
|
||||
import type {
|
||||
LooseRawProps,
|
||||
LooseRawSlots,
|
||||
VaporComponentInstance,
|
||||
} from '../component'
|
||||
import { rawPropsProxyHandlers } from '../componentProps'
|
||||
import { renderEffect } from '../renderEffect'
|
||||
import { extend } from '@vue/shared'
|
||||
import { extend, isArray } from '@vue/shared'
|
||||
import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
|
||||
|
||||
export const teleportStack: TeleportFragment[] = []
|
||||
export const instanceToTeleportMap: WeakMap<
|
||||
VaporComponentInstance,
|
||||
TeleportFragment
|
||||
> = __DEV__ ? new WeakMap() : (null as any)
|
||||
|
||||
/**
|
||||
* dev only.
|
||||
* when the **root** child component updates, synchronously update
|
||||
* the TeleportFragment's children and nodes.
|
||||
*/
|
||||
export function handleTeleportChildrenHmrReload(
|
||||
instance: VaporComponentInstance,
|
||||
newInstance: VaporComponentInstance,
|
||||
): void {
|
||||
const teleport = instanceToTeleportMap.get(instance)
|
||||
if (teleport) {
|
||||
instanceToTeleportMap.set(newInstance, teleport)
|
||||
if (teleport.nodes === instance) {
|
||||
teleport.children = teleport.nodes = newInstance
|
||||
} else if (isArray(teleport.nodes)) {
|
||||
const i = teleport.nodes.indexOf(instance)
|
||||
if (i > -1) {
|
||||
;(teleport.children as Block[])[i] = teleport.nodes[i] = newInstance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const VaporTeleportImpl = {
|
||||
name: 'VaporTeleport',
|
||||
__isTeleport: true,
|
||||
|
@ -34,11 +67,12 @@ export const VaporTeleportImpl = {
|
|||
pauseTracking()
|
||||
const scope = (frag.scope = new EffectScope())
|
||||
scope!.run(() => {
|
||||
let children: Block
|
||||
renderEffect(() => {
|
||||
teleportStack.push(frag)
|
||||
frag.updateChildren(
|
||||
(children = slots.default && (slots.default as BlockFn)()),
|
||||
(frag.children = slots.default && (slots.default as BlockFn)()),
|
||||
)
|
||||
teleportStack.pop()
|
||||
})
|
||||
|
||||
renderEffect(() => {
|
||||
|
@ -48,15 +82,17 @@ export const VaporTeleportImpl = {
|
|||
{},
|
||||
new Proxy(props, rawPropsProxyHandlers) as any as TeleportProps,
|
||||
),
|
||||
children!,
|
||||
frag.children!,
|
||||
)
|
||||
})
|
||||
})
|
||||
resetTracking()
|
||||
|
||||
if (__DEV__) {
|
||||
// TODO
|
||||
;(frag as any).getNodes = () => {
|
||||
// used in normalizeBlock to get the nodes of a TeleportFragment
|
||||
// during hmr update. return empty array if the teleport content
|
||||
// is mounted into the target container.
|
||||
frag.getNodes = () => {
|
||||
return frag.parent !== frag.currentParent ? [] : frag.nodes
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +104,7 @@ export const VaporTeleportImpl = {
|
|||
class TeleportFragment extends VaporFragment {
|
||||
anchor: Node
|
||||
scope: EffectScope | undefined
|
||||
children: Block | undefined
|
||||
|
||||
private targetStart?: Node
|
||||
private mainAnchor?: Node
|
||||
|
@ -178,7 +215,7 @@ class TeleportFragment extends VaporFragment {
|
|||
// remove nodes
|
||||
if (this.nodes) {
|
||||
remove(this.nodes, this.currentParent)
|
||||
this.nodes = []
|
||||
this.children = this.nodes = []
|
||||
}
|
||||
|
||||
// remove anchors
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
mountComponent,
|
||||
unmountComponent,
|
||||
} from './component'
|
||||
import { handleTeleportChildrenHmrReload } from './components/Teleport'
|
||||
|
||||
export function hmrRerender(instance: VaporComponentInstance): void {
|
||||
const normalized = normalizeBlock(instance.block)
|
||||
|
@ -54,5 +55,5 @@ export function hmrReload(
|
|||
)
|
||||
simpleSetCurrentInstance(prev, instance.parent)
|
||||
mountComponent(newInstance, parent, anchor)
|
||||
instance.block = newInstance.block
|
||||
handleTeleportChildrenHmrReload(instance, newInstance)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue