wip: vapor hmr rerender

This commit is contained in:
Evan You 2024-12-08 17:20:34 +08:00
parent 6c4018652b
commit 4833c1c96e
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
6 changed files with 65 additions and 15 deletions

View File

@ -381,6 +381,17 @@ export interface GenericComponentInstance {
// exposed properties via expose()
exposed: Record<string, any> | null
/**
* setup related
* @internal
*/
setupState?: Data
/**
* devtools access to additional info
* @internal
*/
devtoolsRawSetupState?: any
// lifecycle
isMounted: boolean
isUnmounted: boolean
@ -473,6 +484,10 @@ export interface GenericComponentInstance {
* @internal
*/
[LifecycleHooks.SERVER_PREFETCH]?: LifecycleHook<() => Promise<unknown>>
/**
* @internal vapor only
*/
hmrRerender?: () => void
}
/**
@ -584,11 +599,6 @@ export interface ComponentInternalInstance extends GenericComponentInstance {
* @internal
*/
setupState: Data
/**
* devtools access to additional info
* @internal
*/
devtoolsRawSetupState?: any
// main proxy that serves as the public instance (`this`)
proxy: ComponentPublicInstance | null

View File

@ -96,7 +96,8 @@ function rerender(id: string, newRender?: Function): void {
// this flag forces child components with slot content to update
isHmrUpdating = true
if (instance.vapor) {
// TODO
// @ts-expect-error TODO
instance.hmrRerender()
} else {
const i = instance as ComponentInternalInstance
i.renderCache = []

View File

@ -508,3 +508,4 @@ export {
type AppUnmountFn,
} from './apiCreateApp'
export { currentInstance, setCurrentInstance } from './componentCurrentInstance'
export { registerHMR, unregisterHMR } from './hmr'

View File

@ -40,6 +40,7 @@ export class DynamicFragment extends Fragment {
if (this.scope) {
this.scope.off()
parent && remove(this.nodes, parent)
// TODO lifecycle unmount
}
if (render) {

View File

@ -14,6 +14,7 @@ import {
nextUid,
popWarningContext,
pushWarningContext,
registerHMR,
setCurrentInstance,
warn,
} from '@vue/runtime-dom'
@ -40,6 +41,7 @@ import {
getSlot,
} from './componentSlots'
import { insert } from './dom/node'
import { hmrRerender } from './hmr'
export { currentInstance } from '@vue/runtime-dom'
@ -139,15 +141,13 @@ export function createComponent(
)
instance.block = []
} else {
instance.setupState = setupResult
instance.block = component.render.call(
null,
proxyRefs(setupResult),
instance.props,
instance.emit,
instance.attrs,
instance.slots,
)
instance.devtoolsRawSetupState = setupResult
instance.setupState = proxyRefs(setupResult)
devRender(instance)
// HMR
registerHMR(instance)
instance.hmrRerender = hmrRerender.bind(null, instance)
}
} else {
// in prod result can only be block
@ -177,6 +177,20 @@ export function createComponent(
return instance
}
/**
* dev only
*/
export function devRender(instance: VaporComponentInstance): void {
instance.block = instance.type.render!.call(
null,
instance.setupState,
instance.props,
instance.emit,
instance.attrs,
instance.slots,
)
}
const emptyContext: GenericAppContext = {
app: null as any,
config: {},
@ -238,6 +252,8 @@ export class VaporComponentInstance implements GenericComponentInstance {
// dev only
setupState?: Record<string, any>
devtoolsRawSetupState?: any
hmrRerender?: () => void
propsOptions?: NormalizedPropsOptions
emitsOptions?: ObjectEmitsOptions | null

View File

@ -0,0 +1,21 @@
import {
popWarningContext,
pushWarningContext,
setCurrentInstance,
} from '@vue/runtime-core'
import { normalizeBlock } from './block'
import { type VaporComponentInstance, devRender } from './component'
import { insert, remove } from './dom/node'
export function hmrRerender(instance: VaporComponentInstance): void {
const normalized = normalizeBlock(instance.block)
const parent = normalized[0].parentNode!
const anchor = normalized[normalized.length - 1].nextSibling
remove(instance.block, parent)
const reset = setCurrentInstance(instance)
pushWarningContext(instance)
devRender(instance)
reset()
popWarningContext()
insert(instance.block, parent, anchor)
}