mirror of https://github.com/vuejs/core.git
fix(runtime-vapor): `unmountComponent` (#63)
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
This commit is contained in:
parent
9e031275d7
commit
6eaf4b651b
|
@ -0,0 +1,50 @@
|
|||
import {
|
||||
template,
|
||||
children,
|
||||
effect,
|
||||
setText,
|
||||
render,
|
||||
getCurrentInstance,
|
||||
ref,
|
||||
unmountComponent,
|
||||
} from '../src'
|
||||
import type { ComponentInternalInstance } from '../src'
|
||||
import { afterEach, beforeEach, describe, expect } from 'vitest'
|
||||
import { defineComponent, nextTick } from '@vue/runtime-core'
|
||||
|
||||
let host: HTMLElement
|
||||
|
||||
const initHost = () => {
|
||||
host = document.createElement('div')
|
||||
host.setAttribute('id', 'host')
|
||||
document.body.appendChild(host)
|
||||
}
|
||||
beforeEach(() => {
|
||||
initHost()
|
||||
})
|
||||
afterEach(() => {
|
||||
host.remove()
|
||||
})
|
||||
describe('component', () => {
|
||||
test('unmountComponent', async () => {
|
||||
const Comp = defineComponent({
|
||||
setup() {
|
||||
const count = ref(0)
|
||||
const t0 = template('<div></div>')
|
||||
const n0 = t0()
|
||||
const {
|
||||
0: [n1],
|
||||
} = children(n0)
|
||||
effect(() => {
|
||||
setText(n1, void 0, count.value)
|
||||
})
|
||||
return n0
|
||||
},
|
||||
})
|
||||
const instance = render(Comp as any, {}, '#host')
|
||||
await nextTick()
|
||||
expect(host.innerHTML).toBe('<div>0</div>')
|
||||
unmountComponent(instance)
|
||||
expect(host.innerHTML).toBe('')
|
||||
})
|
||||
})
|
|
@ -42,7 +42,9 @@ export function append(parent: ParentBlock, ...nodes: Node[]) {
|
|||
}
|
||||
|
||||
export function remove(block: Block, parent: ParentNode) {
|
||||
if (block instanceof Node) {
|
||||
if (block instanceof DocumentFragment) {
|
||||
remove(Array.from(block.childNodes), parent)
|
||||
} else if (block instanceof Node) {
|
||||
parent.removeChild(block)
|
||||
} else if (isArray(block)) {
|
||||
for (const child of block) remove(child, parent)
|
||||
|
@ -52,7 +54,7 @@ export function remove(block: Block, parent: ParentNode) {
|
|||
}
|
||||
}
|
||||
|
||||
export function setText(el: Element, oldVal: any, newVal: any) {
|
||||
export function setText(el: Node, oldVal: any, newVal: any) {
|
||||
if ((newVal = toDisplayString(newVal)) !== oldVal) {
|
||||
el.textContent = newVal
|
||||
}
|
||||
|
@ -104,7 +106,7 @@ export function setDynamicProp(el: Element, key: string, val: any) {
|
|||
}
|
||||
|
||||
type Children = Record<number, [ChildNode, Children]>
|
||||
export function children(n: ChildNode): Children {
|
||||
export function children(n: Node): Children {
|
||||
return { ...Array.from(n.childNodes).map((n) => [n, children(n)]) }
|
||||
}
|
||||
|
||||
|
|
|
@ -44,3 +44,4 @@ export * from './scheduler'
|
|||
export * from './directive'
|
||||
export * from './dom'
|
||||
export * from './directives/vShow'
|
||||
export { getCurrentInstance, type ComponentInternalInstance } from './component'
|
||||
|
|
|
@ -54,12 +54,15 @@ export function mountComponent(
|
|||
new Proxy({ _: instance }, PublicInstanceProxyHandlers),
|
||||
)
|
||||
const state = setupFn && setupFn(props, ctx)
|
||||
let block: Block | null = null
|
||||
if (state && '__isScriptSetup' in state) {
|
||||
instance.setupState = proxyRefs(state)
|
||||
return (instance.block = component.render(instance.proxy))
|
||||
block = component.render(instance.proxy)
|
||||
} else {
|
||||
return (instance.block = state as Block)
|
||||
block = state as Block
|
||||
}
|
||||
if (block instanceof DocumentFragment) block = Array.from(block.childNodes)
|
||||
return (instance.block = block)
|
||||
})!
|
||||
invokeDirectiveHook(instance, 'beforeMount')
|
||||
insert(block, instance.container)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export const template = (str: string): (() => Node) => {
|
||||
export const template = (str: string): (() => DocumentFragment) => {
|
||||
let cached = false
|
||||
let node: DocumentFragment
|
||||
return () => {
|
||||
|
@ -14,7 +14,7 @@ export const template = (str: string): (() => Node) => {
|
|||
// repeated renders: clone from cache. This is more performant and
|
||||
// efficient when dealing with big lists where the template is repeated
|
||||
// many times.
|
||||
return node.cloneNode(true)
|
||||
return node.cloneNode(true) as DocumentFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import { template } from '@vue/runtime-vapor'
|
||||
|
||||
export default () => {
|
||||
return template('<div>')()
|
||||
}
|
Loading…
Reference in New Issue