@@ -45,6 +45,7 @@ let postTransforms
4545let platformIsPreTag
4646let platformMustUseProp
4747let platformGetTagNamespace
48+ let maybeComponent
4849
4950export function createASTElement (
5051 tag : string ,
@@ -74,6 +75,8 @@ export function parse (
7475 platformIsPreTag = options . isPreTag || no
7576 platformMustUseProp = options . mustUseProp || no
7677 platformGetTagNamespace = options . getTagNamespace || no
78+ const isReservedTag = options . isReservedTag || no
79+ maybeComponent = ( el : ASTElement ) => ! ! el . component || ! isReservedTag ( el . tag )
7780
7881 transforms = pluckModuleFunction ( options . modules , 'transformNode' )
7982 preTransforms = pluckModuleFunction ( options . modules , 'preTransformNode' )
@@ -390,7 +393,8 @@ export function processElement (
390393 )
391394
392395 processRef ( element )
393- processSlot ( element )
396+ processSlotContent ( element )
397+ processSlotOutlet ( element )
394398 processComponent ( element )
395399 for ( let i = 0 ; i < transforms . length ; i ++ ) {
396400 element = transforms [ i ] ( element , options ) || element
@@ -542,7 +546,79 @@ function processOnce (el) {
542546 }
543547}
544548
545- function processSlot ( el ) {
549+ // handle content being passed to a component as slot,
550+ // e.g. <template slot="xxx">, <div slot-scope="xxx">
551+ function processSlotContent ( el ) {
552+ let slotScope
553+ if ( el . tag === 'template' ) {
554+ slotScope = getAndRemoveAttr ( el , 'scope' )
555+ /* istanbul ignore if */
556+ if ( process . env . NODE_ENV !== 'production' && slotScope ) {
557+ warn (
558+ `the "scope" attribute for scoped slots have been deprecated and ` +
559+ `replaced by "slot-scope" since 2.5. The new "slot-scope" attribute ` +
560+ `can also be used on plain elements in addition to <template> to ` +
561+ `denote scoped slots.` ,
562+ el . rawAttrsMap [ 'scope' ] ,
563+ true
564+ )
565+ }
566+ el . slotScope = (
567+ slotScope ||
568+ getAndRemoveAttr ( el , 'slot-scope' ) ||
569+ // new in 2.6: slot-props and its shorthand works the same as slot-scope
570+ // when used on <template> containers
571+ getAndRemoveAttr ( el , 'slot-props' ) ||
572+ getAndRemoveAttr ( el , '()' )
573+ )
574+ } else if ( ( slotScope = getAndRemoveAttr ( el , 'slot-scope' ) ) ) {
575+ /* istanbul ignore if */
576+ if ( process . env . NODE_ENV !== 'production' && el . attrsMap [ 'v-for' ] ) {
577+ warn (
578+ `Ambiguous combined usage of slot-scope and v-for on <${ el . tag } > ` +
579+ `(v-for takes higher priority). Use a wrapper <template> for the ` +
580+ `scoped slot to make it clearer.` ,
581+ el . rawAttrsMap [ 'slot-scope' ] ,
582+ true
583+ )
584+ }
585+ el . slotScope = slotScope
586+ } else {
587+ // 2.6: slot-props on component, denotes default slot
588+ slotScope = getAndRemoveAttr ( el , 'slot-props' ) || getAndRemoveAttr ( el , '()' )
589+ if ( slotScope ) {
590+ if ( process . env . NODE_ENV !== 'production' && ! maybeComponent ( el ) ) {
591+ warn (
592+ `slot-props cannot be used on non-component elements.` ,
593+ el . rawAttrsMap [ 'slot-props' ] || el . rawAttrsMap [ '()' ]
594+ )
595+ }
596+ // add the component's children to its default slot
597+ const slots = el . scopedSlots || ( el . scopedSlots = { } )
598+ const slotContainer = slots [ `"default"` ] = createASTElement ( 'template' , [ ] , el )
599+ slotContainer . children = el . children
600+ slotContainer . slotScope = slotScope
601+ // remove children as they are returned from scopedSlots now
602+ el . children = [ ]
603+ // mark el non-plain so data gets generated
604+ el . plain = false
605+ }
606+ }
607+
608+ // slot="xxx"
609+ const slotTarget = getBindingAttr ( el , 'slot' )
610+ if ( slotTarget ) {
611+ el . slotTarget = slotTarget === '""' ? '"default"' : slotTarget
612+ // preserve slot as an attribute for native shadow DOM compat
613+ // only for non-scoped slots.
614+ if ( el . tag !== 'template' && ! el . slotScope ) {
615+ addAttr ( el , 'slot' , slotTarget , getRawBindingAttr ( el , 'slot' ) )
616+ }
617+ }
618+ }
619+
620+ // handle <slot/> outlets
621+ function processSlotOutlet ( el ) {
546622 if ( el . tag === 'slot' ) {
547623 el . slotName = getBindingAttr ( el , 'name' )
548624 if ( process . env . NODE_ENV !== 'production' && el . key ) {
@@ -553,44 +629,6 @@ function processSlot (el) {
553629 getRawBindingAttr ( el , 'key' )
554630 )
555631 }
556- } else {
557- let slotScope
558- if ( el . tag === 'template' ) {
559- slotScope = getAndRemoveAttr ( el , 'scope' )
560- /* istanbul ignore if */
561- if ( process . env . NODE_ENV !== 'production' && slotScope ) {
562- warn (
563- `the "scope" attribute for scoped slots have been deprecated and ` +
564- `replaced by "slot-scope" since 2.5. The new "slot-scope" attribute ` +
565- `can also be used on plain elements in addition to <template> to ` +
566- `denote scoped slots.` ,
567- el . rawAttrsMap [ 'scope' ] ,
568- true
569- )
570- }
571- el . slotScope = slotScope || getAndRemoveAttr ( el , 'slot-scope' )
572- } else if ( ( slotScope = getAndRemoveAttr ( el , 'slot-scope' ) ) ) {
573- /* istanbul ignore if */
574- if ( process . env . NODE_ENV !== 'production' && el . attrsMap [ 'v-for' ] ) {
575- warn (
576- `Ambiguous combined usage of slot-scope and v-for on <${ el . tag } > ` +
577- `(v-for takes higher priority). Use a wrapper <template> for the ` +
578- `scoped slot to make it clearer.` ,
579- el . rawAttrsMap [ 'slot-scope' ] ,
580- true
581- )
582- }
583- el . slotScope = slotScope
584- }
585- const slotTarget = getBindingAttr ( el , 'slot' )
586- if ( slotTarget ) {
587- el . slotTarget = slotTarget === '""' ? '"default"' : slotTarget
588- // preserve slot as an attribute for native shadow DOM compat
589- // only for non-scoped slots.
590- if ( el . tag !== 'template' && ! el . slotScope ) {
591- addAttr ( el , 'slot' , slotTarget , getRawBindingAttr ( el , 'slot' ) )
592- }
593- }
594632 }
595633}
596634
0 commit comments