]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat: add isCustomElement option (#299)
author月迷津渡 <CodeDaraW@gmail.com>
Tue, 15 Oct 2019 21:30:47 +0000 (05:30 +0800)
committerEvan You <yyx990803@gmail.com>
Tue, 15 Oct 2019 21:30:47 +0000 (17:30 -0400)
packages/compiler-core/__tests__/parse.spec.ts
packages/compiler-core/src/parse.ts
packages/runtime-core/src/apiApp.ts
packages/runtime-core/src/component.ts
packages/vue/__tests__/index.spec.ts

index 3e0ccef7986bf8b85990c71e6df6d0fdfce3cb84..4237b5faf7b01ab19f554308025cc0b3808bdff8 100644 (file)
@@ -616,6 +616,25 @@ describe('compiler: parse', () => {
       })
     })
 
+    test('custom element', () => {
+      const ast = parse('<div></div><comp></comp>', {
+        isNativeTag: tag => tag === 'div',
+        isCustomElement: tag => tag === 'comp'
+      })
+
+      expect(ast.children[0]).toMatchObject({
+        type: NodeTypes.ELEMENT,
+        tag: 'div',
+        tagType: ElementTypes.ELEMENT
+      })
+
+      expect(ast.children[1]).toMatchObject({
+        type: NodeTypes.ELEMENT,
+        tag: 'comp',
+        tagType: ElementTypes.ELEMENT
+      })
+    })
+
     test('attribute with no value', () => {
       const ast = parse('<div id></div>')
       const element = ast.children[0] as ElementNode
index 2c39a28c4f508ad0e665cd44f3ee71743796bd15..640298189679c4a6985113c6ff8432d6a4ae642c 100644 (file)
@@ -32,6 +32,7 @@ import { extend } from '@vue/shared'
 export interface ParserOptions {
   isVoidTag?: (tag: string) => boolean // e.g. img, br, hr
   isNativeTag?: (tag: string) => boolean // e.g. loading-indicator in weex
+  isCustomElement?: (tag: string) => boolean
   getNamespace?: (tag: string, parent: ElementNode | undefined) => Namespace
   getTextMode?: (tag: string, ns: Namespace) => TextModes
   delimiters?: [string, string] // ['{{', '}}']
@@ -54,6 +55,7 @@ export const defaultParserOptions: MergedParserOptions = {
   getNamespace: () => Namespaces.HTML,
   getTextMode: () => TextModes.DATA,
   isVoidTag: NO,
+  isCustomElement: NO,
   namedCharacterReferences: {
     'gt;': '>',
     'lt;': '<',
@@ -433,7 +435,7 @@ function parseTag(
   }
 
   let tagType = ElementTypes.ELEMENT
-  if (!context.inPre) {
+  if (!context.inPre && !context.options.isCustomElement(tag)) {
     if (context.options.isNativeTag) {
       if (!context.options.isNativeTag(tag)) tagType = ElementTypes.COMPONENT
     } else {
index d7f393bc8d9820bb78a365c4a5631424ef3fa30b..31d61047aa15c1a749dae902e302a5662c1f9a50 100644 (file)
@@ -28,6 +28,7 @@ export interface AppConfig {
   devtools: boolean
   performance: boolean
   readonly isNativeTag?: (tag: string) => boolean
+  isCustomElement?: (tag: string) => boolean
   errorHandler?: (
     err: Error,
     instance: ComponentPublicInstance | null,
@@ -62,6 +63,7 @@ export function createAppContext(): AppContext {
       devtools: true,
       performance: false,
       isNativeTag: NO,
+      isCustomElement: NO,
       errorHandler: undefined,
       warnHandler: undefined
     },
index 72c3fdac3f5ecde37c419d4c59dd39a242c54b72..20328af9e27ccde7e55ed5269f38544badaca0c5 100644 (file)
@@ -350,6 +350,7 @@ function finishComponentSetup(
     if (__RUNTIME_COMPILE__ && Component.template && !Component.render) {
       if (compile) {
         Component.render = compile(Component.template, {
+          isCustomElement: instance.appContext.config.isCustomElement || NO,
           onError(err: CompilerError) {
             if (__DEV__) {
               const message = `Template compilation error: ${err.message}`
index 754b717a69b652644d699fd6595fc0c8dfec919c..d121360dbc8989ed7406f4f2b0aa54604136a488 100644 (file)
@@ -29,3 +29,14 @@ it('should correctly normalize class with on-the-fly template compilation', () =
   expect(classes.contains('test')).toBe(true)
   expect(classes.contains('test2')).toBe(false)
 })
+
+it('should support custom element', () => {
+  const app = createApp()
+  const container = document.createElement('div')
+  const App = {
+    template: '<custom></custom>'
+  }
+  app.config.isCustomElement = tag => tag === 'custom'
+  app.mount(App, container)
+  expect(container.innerHTML).toBe('<custom></custom>')
+})