From 6a92bbd9c0e6ccc8bbea4119930292df64f09f3e Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 24 Oct 2019 21:58:34 -0400 Subject: [PATCH] feat(runtime-dom): support using mount target innerHTML as template --- packages/runtime-core/src/apiApp.ts | 4 +- packages/runtime-core/src/createRenderer.ts | 19 +++----- packages/runtime-dom/src/index.ts | 51 ++++++++++++++++----- 3 files changed, 47 insertions(+), 27 deletions(-) diff --git a/packages/runtime-core/src/apiApp.ts b/packages/runtime-core/src/apiApp.ts index 18afa463..da3d50b9 100644 --- a/packages/runtime-core/src/apiApp.ts +++ b/packages/runtime-core/src/apiApp.ts @@ -18,7 +18,7 @@ export interface App { directive(name: string, directive: Directive): this mount( rootComponent: Component, - rootContainer: HostElement, + rootContainer: HostElement | string, rootProps?: Data ): ComponentPublicInstance provide(key: InjectionKey | string, value: T): void @@ -141,7 +141,7 @@ export function createAppAPI( mount( rootComponent: Component, - rootContainer: string | HostElement, + rootContainer: HostElement, rootProps?: Data ): any { if (!isMounted) { diff --git a/packages/runtime-core/src/createRenderer.ts b/packages/runtime-core/src/createRenderer.ts index 5508c38f..ed55fe0a 100644 --- a/packages/runtime-core/src/createRenderer.ts +++ b/packages/runtime-core/src/createRenderer.ts @@ -123,7 +123,7 @@ export interface RendererOptions { export type RootRenderFunction = ( vnode: VNode | null, - dom: HostElement | string + dom: HostElement ) => void /** @@ -1858,19 +1858,12 @@ export function createRenderer< } } - function render(vnode: HostVNode | null, rawContainer: HostElement | string) { - let container: any = rawContainer - if (isString(container)) { - container = hostQuerySelector(container) - if (!container) { - if (__DEV__) { - warn( - `Failed to locate root container: ` + `querySelector returned null.` - ) - } - return - } + const render: RootRenderFunction< + HostNode, + HostElement & { + _vnode: HostVNode | null } + > = (vnode, container) => { if (vnode == null) { if (container._vnode) { unmount(container._vnode, null, null, true) diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index 267e004b..7550cc6c 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -1,27 +1,54 @@ -import { createRenderer } from '@vue/runtime-core' +import { createRenderer, warn } from '@vue/runtime-core' import { nodeOps } from './nodeOps' import { patchProp } from './patchProp' // Importing from the compiler, will be tree-shaken in prod import { isHTMLTag, isSVGTag } from '@vue/compiler-dom' +import { isFunction, isString } from '@vue/shared' -const { render, createApp } = createRenderer({ +const { render, createApp: baseCreateApp } = createRenderer({ patchProp, ...nodeOps }) -const wrappedCreateApp = () => { - const app = createApp() - // inject `isNativeTag` dev only - Object.defineProperty(app.config, 'isNativeTag', { - value: (tag: string) => isHTMLTag(tag) || isSVGTag(tag), - writable: false - }) +const createApp = () => { + const app = baseCreateApp() + + if (__DEV__) { + // Inject `isNativeTag` + // this is used for component name validation (dev only) + Object.defineProperty(app.config, 'isNativeTag', { + value: (tag: string) => isHTMLTag(tag) || isSVGTag(tag), + writable: false + }) + } + + const mount = app.mount + app.mount = (component, container, props): any => { + if (isString(container)) { + container = document.querySelector(container)! + if (!container) { + __DEV__ && + warn(`Failed to mount app: mount target selector returned null.`) + return + } + } + if ( + __RUNTIME_COMPILE__ && + !isFunction(component) && + !component.render && + !component.template + ) { + component.template = container.innerHTML + } + // clear content before mounting + container.innerHTML = '' + return mount(component, container, props) + } + return app } -const exportedCreateApp = __DEV__ ? wrappedCreateApp : createApp - -export { render, exportedCreateApp as createApp } +export { render, createApp } // DOM-only runtime helpers export {