feat(compiler-core): support v-is
see https://github.com/vuejs/rfcs/pull/149 for details
This commit is contained in:
		
							parent
							
								
									d777ac6549
								
							
						
					
					
						commit
						b8ffbffaf7
					
				@ -646,6 +646,55 @@ describe('compiler: parse', () => {
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    test('v-is without `isNativeTag`', () => {
 | 
			
		||||
      const ast = baseParse(
 | 
			
		||||
        `<div></div><div v-is="'foo'"></div><Comp></Comp>`,
 | 
			
		||||
        {
 | 
			
		||||
          isNativeTag: tag => tag === 'div'
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      expect(ast.children[0]).toMatchObject({
 | 
			
		||||
        type: NodeTypes.ELEMENT,
 | 
			
		||||
        tag: 'div',
 | 
			
		||||
        tagType: ElementTypes.ELEMENT
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      expect(ast.children[1]).toMatchObject({
 | 
			
		||||
        type: NodeTypes.ELEMENT,
 | 
			
		||||
        tag: 'div',
 | 
			
		||||
        tagType: ElementTypes.COMPONENT
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      expect(ast.children[2]).toMatchObject({
 | 
			
		||||
        type: NodeTypes.ELEMENT,
 | 
			
		||||
        tag: 'Comp',
 | 
			
		||||
        tagType: ElementTypes.COMPONENT
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    test('v-is with `isNativeTag`', () => {
 | 
			
		||||
      const ast = baseParse(`<div></div><div v-is="'foo'"></div><Comp></Comp>`)
 | 
			
		||||
 | 
			
		||||
      expect(ast.children[0]).toMatchObject({
 | 
			
		||||
        type: NodeTypes.ELEMENT,
 | 
			
		||||
        tag: 'div',
 | 
			
		||||
        tagType: ElementTypes.ELEMENT
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      expect(ast.children[1]).toMatchObject({
 | 
			
		||||
        type: NodeTypes.ELEMENT,
 | 
			
		||||
        tag: 'div',
 | 
			
		||||
        tagType: ElementTypes.COMPONENT
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      expect(ast.children[2]).toMatchObject({
 | 
			
		||||
        type: NodeTypes.ELEMENT,
 | 
			
		||||
        tag: 'Comp',
 | 
			
		||||
        tagType: ElementTypes.COMPONENT
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    test('custom element', () => {
 | 
			
		||||
      const ast = baseParse('<div></div><comp></comp>', {
 | 
			
		||||
        isNativeTag: tag => tag === 'div',
 | 
			
		||||
 | 
			
		||||
@ -829,6 +829,25 @@ describe('compiler: element transform', () => {
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    test('v-is', () => {
 | 
			
		||||
      const { node, root } = parseWithBind(`<div v-is="'foo'" />`)
 | 
			
		||||
      expect(root.helpers).toContain(RESOLVE_DYNAMIC_COMPONENT)
 | 
			
		||||
      expect(node).toMatchObject({
 | 
			
		||||
        tag: {
 | 
			
		||||
          callee: RESOLVE_DYNAMIC_COMPONENT,
 | 
			
		||||
          arguments: [
 | 
			
		||||
            {
 | 
			
		||||
              type: NodeTypes.SIMPLE_EXPRESSION,
 | 
			
		||||
              content: `'foo'`,
 | 
			
		||||
              isStatic: false
 | 
			
		||||
            }
 | 
			
		||||
          ]
 | 
			
		||||
        },
 | 
			
		||||
        // should skip v-is runtime check
 | 
			
		||||
        directives: undefined
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('<svg> should be forced into blocks', () => {
 | 
			
		||||
 | 
			
		||||
@ -451,9 +451,13 @@ function parseTag(
 | 
			
		||||
  let tagType = ElementTypes.ELEMENT
 | 
			
		||||
  const options = context.options
 | 
			
		||||
  if (!context.inPre && !options.isCustomElement(tag)) {
 | 
			
		||||
    if (options.isNativeTag) {
 | 
			
		||||
    const hasVIs = props.some(
 | 
			
		||||
      p => p.type === NodeTypes.DIRECTIVE && p.name === 'is'
 | 
			
		||||
    )
 | 
			
		||||
    if (options.isNativeTag && !hasVIs) {
 | 
			
		||||
      if (!options.isNativeTag(tag)) tagType = ElementTypes.COMPONENT
 | 
			
		||||
    } else if (
 | 
			
		||||
      hasVIs ||
 | 
			
		||||
      isCoreComponent(tag) ||
 | 
			
		||||
      (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
 | 
			
		||||
      /^[A-Z]/.test(tag) ||
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,8 @@ import {
 | 
			
		||||
  toValidAssetId,
 | 
			
		||||
  findProp,
 | 
			
		||||
  isCoreComponent,
 | 
			
		||||
  isBindKey
 | 
			
		||||
  isBindKey,
 | 
			
		||||
  findDir
 | 
			
		||||
} from '../utils'
 | 
			
		||||
import { buildSlots } from './vSlot'
 | 
			
		||||
import { isStaticNode } from './hoistStatic'
 | 
			
		||||
@ -202,7 +203,8 @@ export function resolveComponentType(
 | 
			
		||||
  const { tag } = node
 | 
			
		||||
 | 
			
		||||
  // 1. dynamic component
 | 
			
		||||
  const isProp = node.tag === 'component' && findProp(node, 'is')
 | 
			
		||||
  const isProp =
 | 
			
		||||
    node.tag === 'component' ? findProp(node, 'is') : findDir(node, 'is')
 | 
			
		||||
  if (isProp) {
 | 
			
		||||
    const exp =
 | 
			
		||||
      isProp.type === NodeTypes.ATTRIBUTE
 | 
			
		||||
@ -340,8 +342,11 @@ export function buildProps(
 | 
			
		||||
      if (name === 'once') {
 | 
			
		||||
        continue
 | 
			
		||||
      }
 | 
			
		||||
      // skip :is on <component>
 | 
			
		||||
      if (isBind && tag === 'component' && isBindKey(arg, 'is')) {
 | 
			
		||||
      // skip v-is and :is on <component>
 | 
			
		||||
      if (
 | 
			
		||||
        name === 'is' ||
 | 
			
		||||
        (isBind && tag === 'component' && isBindKey(arg, 'is'))
 | 
			
		||||
      ) {
 | 
			
		||||
        continue
 | 
			
		||||
      }
 | 
			
		||||
      // skip v-on in SSR compilation
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user