feat(core): support dynamic component via <component :is> (#320)

This commit is contained in:
宋铄运
2019-10-19 00:09:04 +08:00
committed by Evan You
parent d179918001
commit 7f23eaf661
6 changed files with 133 additions and 22 deletions

View File

@@ -5,7 +5,8 @@ import {
resolveComponent,
resolveDirective,
Component,
Directive
Directive,
resolveDynamicComponent
} from '@vue/runtime-test'
describe('resolveAssets', () => {
@@ -90,5 +91,30 @@ describe('resolveAssets', () => {
expect('Failed to resolve component: foo').toHaveBeenWarned()
expect('Failed to resolve directive: bar').toHaveBeenWarned()
})
test('resolve dynamic component', () => {
const app = createApp()
const dynamicComponents = {
foo: () => 'foo',
bar: () => 'bar',
baz: { render: () => 'baz' }
}
let foo, bar, baz // dynamic components
const Root = {
components: { foo: dynamicComponents.foo },
setup() {
return () => {
foo = resolveDynamicComponent('foo') // <component is="foo"/>
bar = resolveDynamicComponent(dynamicComponents.bar) // <component :is="bar"/>, function
baz = resolveDynamicComponent(dynamicComponents.baz) // <component :is="baz"/>, object
}
}
}
const root = nodeOps.createElement('div')
app.mount(Root, root)
expect(foo).toBe(dynamicComponents.foo)
expect(bar).toBe(dynamicComponents.bar)
expect(baz).toBe(dynamicComponents.baz)
})
})
})

View File

@@ -1,13 +1,30 @@
import { currentRenderingInstance } from '../componentRenderUtils'
import { currentInstance, Component } from '../component'
import { Directive } from '../directives'
import { camelize, capitalize } from '@vue/shared'
import {
camelize,
capitalize,
isString,
isObject,
isFunction
} from '@vue/shared'
import { warn } from '../warning'
export function resolveComponent(name: string): Component | undefined {
return resolveAsset('components', name)
}
export function resolveDynamicComponent(
component: unknown
): Component | undefined {
if (!component) return
if (isString(component)) {
return resolveAsset('components', component)
} else if (isFunction(component) || isObject(component)) {
return component
}
}
export function resolveDirective(name: string): Directive | undefined {
return resolveAsset('directives', name)
}

View File

@@ -39,7 +39,11 @@ export {
// Internal, for compiler generated code
// should sync with '@vue/compiler-core/src/runtimeConstants.ts'
export { applyDirectives } from './directives'
export { resolveComponent, resolveDirective } from './helpers/resolveAssets'
export {
resolveComponent,
resolveDirective,
resolveDynamicComponent
} from './helpers/resolveAssets'
export { renderList } from './helpers/renderList'
export { toString } from './helpers/toString'
export { toHandlers } from './helpers/toHandlers'