describe('compiler + runtime integration', () => {
mockWarn()
- it('should support on-the-fly template compilation', () => {
+ it('should support runtime template compilation', () => {
const container = document.createElement('div')
const App = {
template: `{{ count }}`,
expect(container.innerHTML).toBe(`0`)
})
+ it('should support runtime template via CSS ID selector', () => {
+ const container = document.createElement('div')
+ const template = document.createElement('div')
+ template.id = 'template'
+ template.innerHTML = '{{ count }}'
+ document.body.appendChild(template)
+
+ const App = {
+ template: `#template`,
+ data() {
+ return {
+ count: 0
+ }
+ }
+ }
+ createApp().mount(App, container)
+ expect(container.innerHTML).toBe(`0`)
+ })
+
+ it('should support runtime template via direct DOM node', () => {
+ const container = document.createElement('div')
+ const template = document.createElement('div')
+ template.id = 'template'
+ template.innerHTML = '{{ count }}'
+
+ const App = {
+ template,
+ data() {
+ return {
+ count: 0
+ }
+ }
+ }
+ createApp().mount(App, container)
+ expect(container.innerHTML).toBe(`0`)
+ })
+
it('should warn template compilation errors with codeframe', () => {
const container = document.createElement('div')
const App = {
import * as runtimeDom from '@vue/runtime-dom'
import { isString, NOOP } from '@vue/shared'
-const idToTemplateCache = Object.create(null)
+const compileCache: Record<string, RenderFunction> = Object.create(null)
function compileToFunction(
template: string | HTMLElement,
options?: CompilerOptions
): RenderFunction {
- if (isString(template)) {
- if (template[0] === '#') {
- if (template in idToTemplateCache) {
- template = idToTemplateCache[template]
- } else {
- const el = document.querySelector(template)
- if (__DEV__ && !el) {
- warn(`Template element not found or is empty: ${template}`)
- }
- template = idToTemplateCache[template] = el ? el.innerHTML : ``
- }
+ if (!isString(template)) {
+ if (template.nodeType) {
+ template = template.innerHTML
+ } else {
+ __DEV__ && warn(`invalid template option: `, template)
+ return NOOP
}
- } else if (template.nodeType) {
- template = template.innerHTML
- } else {
- __DEV__ && warn(`invalid template option: `, template)
- return NOOP
}
- const { code } = compile(template as string, {
+ const key = template
+ const cached = compileCache[key]
+ if (cached) {
+ return cached
+ }
+
+ if (template[0] === '#') {
+ const el = document.querySelector(template)
+ if (__DEV__ && !el) {
+ warn(`Template element not found or is empty: ${template}`)
+ }
+ template = el ? el.innerHTML : ``
+ }
+
+ const { code } = compile(template, {
hoistStatic: true,
cacheHandlers: true,
...options
const render = new Function('Vue', code)(runtimeDom) as RenderFunction
render.isRuntimeCompiled = true
- return render
+ return (compileCache[key] = render)
}
registerRuntimeCompiler(compileToFunction)