@@ -6,11 +6,14 @@ import {
|
||||
Component,
|
||||
Directive,
|
||||
resolveDynamicComponent,
|
||||
h
|
||||
h,
|
||||
serializeInner
|
||||
} from '@vue/runtime-test'
|
||||
import { mockWarn } from '@vue/shared'
|
||||
|
||||
describe('resolveAssets', () => {
|
||||
mockWarn()
|
||||
|
||||
test('should work', () => {
|
||||
const FooBar = () => null
|
||||
const BarBaz = { mounted: () => null }
|
||||
@@ -63,8 +66,6 @@ describe('resolveAssets', () => {
|
||||
})
|
||||
|
||||
describe('warning', () => {
|
||||
mockWarn()
|
||||
|
||||
test('used outside render() or setup()', () => {
|
||||
resolveComponent('foo')
|
||||
expect(
|
||||
@@ -128,5 +129,22 @@ describe('resolveAssets', () => {
|
||||
expect(bar).toBe(dynamicComponents.bar)
|
||||
expect(baz).toBe(dynamicComponents.baz)
|
||||
})
|
||||
|
||||
test('resolve dynamic component should fallback to plain element without warning', () => {
|
||||
const Root = {
|
||||
setup() {
|
||||
return () => {
|
||||
return h(resolveDynamicComponent('div') as string, null, {
|
||||
default: () => 'hello'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp(Root)
|
||||
const root = nodeOps.createElement('div')
|
||||
app.mount(root)
|
||||
expect(serializeInner(root)).toBe('<div>hello</div>')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('vnode', () => {
|
||||
const vnode = createVNode('p', null, ['foo'])
|
||||
expect(vnode.children).toMatchObject(['foo'])
|
||||
expect(vnode.shapeFlag).toBe(
|
||||
ShapeFlags.ELEMENT + ShapeFlags.ARRAY_CHILDREN
|
||||
ShapeFlags.ELEMENT | ShapeFlags.ARRAY_CHILDREN
|
||||
)
|
||||
})
|
||||
|
||||
@@ -114,7 +114,7 @@ describe('vnode', () => {
|
||||
const vnode = createVNode('p', null, { foo: 'foo' })
|
||||
expect(vnode.children).toMatchObject({ foo: 'foo' })
|
||||
expect(vnode.shapeFlag).toBe(
|
||||
ShapeFlags.ELEMENT + ShapeFlags.SLOTS_CHILDREN
|
||||
ShapeFlags.ELEMENT | ShapeFlags.SLOTS_CHILDREN
|
||||
)
|
||||
})
|
||||
|
||||
@@ -122,7 +122,7 @@ describe('vnode', () => {
|
||||
const vnode = createVNode('p', null, nop)
|
||||
expect(vnode.children).toMatchObject({ default: nop })
|
||||
expect(vnode.shapeFlag).toBe(
|
||||
ShapeFlags.ELEMENT + ShapeFlags.SLOTS_CHILDREN
|
||||
ShapeFlags.ELEMENT | ShapeFlags.SLOTS_CHILDREN
|
||||
)
|
||||
})
|
||||
|
||||
@@ -130,7 +130,19 @@ describe('vnode', () => {
|
||||
const vnode = createVNode('p', null, 'foo')
|
||||
expect(vnode.children).toBe('foo')
|
||||
expect(vnode.shapeFlag).toBe(
|
||||
ShapeFlags.ELEMENT + ShapeFlags.TEXT_CHILDREN
|
||||
ShapeFlags.ELEMENT | ShapeFlags.TEXT_CHILDREN
|
||||
)
|
||||
})
|
||||
|
||||
test('element with slots', () => {
|
||||
const children = [createVNode('span', null, 'hello')]
|
||||
const vnode = createVNode('div', null, {
|
||||
default: () => children
|
||||
})
|
||||
|
||||
expect(vnode.children).toBe(children)
|
||||
expect(vnode.shapeFlag).toBe(
|
||||
ShapeFlags.ELEMENT | ShapeFlags.ARRAY_CHILDREN
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,10 +24,14 @@ export function resolveComponent(name: string): Component | undefined {
|
||||
|
||||
export function resolveDynamicComponent(
|
||||
component: unknown
|
||||
): Component | undefined {
|
||||
): Component | string | undefined {
|
||||
if (!component) return
|
||||
if (isString(component)) {
|
||||
return resolveAsset(COMPONENTS, component, currentRenderingInstance)
|
||||
return (
|
||||
resolveAsset(COMPONENTS, component, currentRenderingInstance, false) ||
|
||||
// fallback to plain element
|
||||
component
|
||||
)
|
||||
} else if (isFunction(component) || isObject(component)) {
|
||||
return component
|
||||
}
|
||||
@@ -41,7 +45,8 @@ export function resolveDirective(name: string): Directive | undefined {
|
||||
function resolveAsset(
|
||||
type: typeof COMPONENTS,
|
||||
name: string,
|
||||
instance?: ComponentInternalInstance | null
|
||||
instance?: ComponentInternalInstance | null,
|
||||
warnMissing?: boolean
|
||||
): Component | undefined
|
||||
// overload 2: directives
|
||||
function resolveAsset(
|
||||
@@ -54,7 +59,8 @@ function resolveAsset(
|
||||
type: typeof COMPONENTS | typeof DIRECTIVES,
|
||||
name: string,
|
||||
instance: ComponentInternalInstance | null = currentRenderingInstance ||
|
||||
currentInstance
|
||||
currentInstance,
|
||||
warnMissing = true
|
||||
) {
|
||||
if (instance) {
|
||||
let camelized, capitalized
|
||||
@@ -75,7 +81,8 @@ function resolveAsset(
|
||||
res = self
|
||||
}
|
||||
}
|
||||
if (__DEV__ && !res) {
|
||||
if (__DEV__ && warnMissing && !res) {
|
||||
debugger
|
||||
warn(`Failed to resolve ${type.slice(0, -1)}: ${name}`)
|
||||
}
|
||||
return res
|
||||
|
||||
@@ -397,9 +397,16 @@ export function normalizeChildren(vnode: VNode, children: unknown) {
|
||||
} else if (isArray(children)) {
|
||||
type = ShapeFlags.ARRAY_CHILDREN
|
||||
} else if (typeof children === 'object') {
|
||||
type = ShapeFlags.SLOTS_CHILDREN
|
||||
if (!(children as RawSlots)._) {
|
||||
;(children as RawSlots)._ctx = currentRenderingInstance
|
||||
// in case <component :is="x"> resolves to native element, the vnode call
|
||||
// will receive slots object.
|
||||
if (vnode.shapeFlag & ShapeFlags.ELEMENT && (children as any).default) {
|
||||
normalizeChildren(vnode, (children as any).default())
|
||||
return
|
||||
} else {
|
||||
type = ShapeFlags.SLOTS_CHILDREN
|
||||
if (!(children as RawSlots)._) {
|
||||
;(children as RawSlots)._ctx = currentRenderingInstance
|
||||
}
|
||||
}
|
||||
} else if (isFunction(children)) {
|
||||
children = { default: children, _ctx: currentRenderingInstance }
|
||||
|
||||
Reference in New Issue
Block a user