| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- import { ref, shallowRef } from '@vue/reactivity'
- import { nextTick, resolveDynamicComponent } from '@vue/runtime-dom'
- import {
- createComponentWithFallback,
- createDynamicComponent,
- defineVaporComponent,
- renderEffect,
- setHtml,
- setInsertionState,
- template,
- } from '../src'
- import { makeRender } from './_utils'
- const define = makeRender()
- describe('api: createDynamicComponent', () => {
- const A = () => document.createTextNode('AAA')
- const B = () => document.createTextNode('BBB')
- test('direct value', async () => {
- const val = shallowRef<any>(A)
- const { html } = define({
- setup() {
- return createDynamicComponent(() => val.value)
- },
- }).render()
- expect(html()).toBe('AAA<!--dynamic-component-->')
- val.value = B
- await nextTick()
- expect(html()).toBe('BBB<!--dynamic-component-->')
- // fallback
- val.value = 'foo'
- await nextTick()
- expect(html()).toBe('<foo></foo><!--dynamic-component-->')
- })
- test('global registration', async () => {
- const val = shallowRef('foo')
- const { app, html, mount } = define({
- setup() {
- return createDynamicComponent(() => val.value)
- },
- }).create()
- app.component('foo', A)
- app.component('bar', B)
- mount()
- expect(html()).toBe('AAA<!--dynamic-component-->')
- val.value = 'bar'
- await nextTick()
- expect(html()).toBe('BBB<!--dynamic-component-->')
- // fallback
- val.value = 'baz'
- await nextTick()
- expect(html()).toBe('<baz></baz><!--dynamic-component-->')
- })
- test('with v-once', async () => {
- const val = shallowRef<any>(A)
- const { html } = define({
- setup() {
- return createDynamicComponent(() => val.value, null, null, true, true)
- },
- }).render()
- expect(html()).toBe('AAA<!--dynamic-component-->')
- val.value = B
- await nextTick()
- expect(html()).toBe('AAA<!--dynamic-component-->') // still AAA
- })
- test('fallback with v-once', async () => {
- const val = shallowRef<any>('button')
- const id = ref(0)
- const { html } = define({
- setup() {
- return createDynamicComponent(
- () => val.value,
- { id: () => id.value },
- null,
- true,
- true,
- )
- },
- }).render()
- expect(html()).toBe('<button id="0"></button><!--dynamic-component-->')
- id.value++
- await nextTick()
- expect(html()).toBe('<button id="0"></button><!--dynamic-component-->')
- })
- test('render fallback with insertionState', async () => {
- const { html, mount } = define({
- setup() {
- const html = ref('hi')
- const n1 = template('<div></div>', true)() as any
- setInsertionState(n1)
- const n0 = createComponentWithFallback(
- resolveDynamicComponent('button') as any,
- ) as any
- renderEffect(() => setHtml(n0, html.value))
- return n1
- },
- }).create()
- mount()
- expect(html()).toBe('<div><button>hi</button></div>')
- })
- test('switch dynamic component children', async () => {
- const CompA = defineVaporComponent({
- setup() {
- return template('<div>A</div>')()
- },
- })
- const CompB = defineVaporComponent({
- setup() {
- return template('<div>B</div>')()
- },
- })
- const current = shallowRef(CompA)
- const { html } = define({
- setup() {
- const t1 = template('<div></div>')
- const n2 = t1() as any
- setInsertionState(n2)
- createDynamicComponent(() => current.value)
- return n2
- },
- }).render()
- expect(html()).toBe('<div><div>A</div><!--dynamic-component--></div>')
- current.value = CompB
- await nextTick()
- expect(html()).toBe('<div><div>B</div><!--dynamic-component--></div>')
- })
- test('fallback with dynamic slots', async () => {
- const slotName = ref('default')
- const { html } = define({
- setup() {
- return createDynamicComponent(() => 'div', null, {
- $: [
- () => ({
- name: slotName.value,
- fn: () => template('<span>hi</span>')(),
- }),
- ] as any,
- })
- },
- }).render()
- expect(html()).toBe(
- '<div><span>hi</span><!--slot--></div><!--dynamic-component-->',
- )
- // update slot name
- slotName.value = 'custom'
- await nextTick()
- expect(html()).toBe('<div><!--slot--></div><!--dynamic-component-->')
- slotName.value = 'default'
- await nextTick()
- expect(html()).toBe(
- '<div><span>hi</span><!--slot--></div><!--dynamic-component-->',
- )
- })
- test('accept blocks', async () => {
- const { html } = define({
- setup() {
- const n0 = template('<a>router link</a>')()
- return createDynamicComponent(() => n0)
- },
- }).render()
- expect(html()).toBe('<a>router link</a><!--dynamic-component-->')
- })
- })
|