File tree Expand file tree Collapse file tree 6 files changed +61
-49
lines changed Expand file tree Collapse file tree 6 files changed +61
-49
lines changed Original file line number Diff line number Diff line change @@ -93,6 +93,8 @@ declare interface Component {
9393 _f : ( id : string ) = > Function ;
9494 // renderList
9595 _l : ( val : any , render : Function ) = > ?Array < VNode > ;
96+ // renderSlot
97+ _t : ( name : string , fallback : ?Array < VNode > ) => ?Array < VNode > ;
9698 // apply v-bind object
9799 _b : ( vnode : VNodeWithData , value : any ) = > void ;
98100 // retrive custom keyCode
Original file line number Diff line number Diff line change @@ -221,11 +221,11 @@ function genText (text: ASTText | ASTExpression): string {
221221}
222222
223223function genSlot ( el : ASTElement ) : string {
224- const slot = `$slots[ ${ el . slotName || '"default"' } ]`
224+ const slotName = el . slotName || '"default"'
225225 const children = genChildren ( el )
226226 return children
227- ? `(${ slot } || ${ children } )`
228- : slot
227+ ? `_t (${ slotName } , ${ children } )`
228+ : `_t( ${ slotName } )`
229229}
230230
231231function genComponent ( el : any ) : string {
Original file line number Diff line number Diff line change @@ -34,7 +34,6 @@ let preTransforms
3434let transforms
3535let postTransforms
3636let delimiters
37- let seenSlots : any
3837
3938/**
4039 * Convert HTML string to AST.
@@ -51,7 +50,6 @@ export function parse (
5150 transforms = pluckModuleFunction ( options . modules , 'transformNode' )
5251 postTransforms = pluckModuleFunction ( options . modules , 'postTransformNode' )
5352 delimiters = options . delimiters
54- seenSlots = Object . create ( null )
5553 const stack = [ ]
5654 const preserveWhitespace = options . preserveWhitespace !== false
5755 let root
@@ -326,25 +324,7 @@ function processOnce (el) {
326324
327325function processSlot ( el ) {
328326 if ( el . tag === 'slot' ) {
329- if ( process . env . NODE_ENV !== 'production' ) {
330- if ( ! el . attrsMap [ ':name' ] && ! el . attrsMap [ 'v-bind:name' ] && checkInFor ( el ) ) {
331- warn (
332- 'Static <slot> found inside v-for: they will not render correctly. ' +
333- 'Render the list in parent scope and use a single <slot> instead.'
334- )
335- }
336- }
337327 el . slotName = getBindingAttr ( el , 'name' )
338- if ( process . env . NODE_ENV !== 'production' ) {
339- const name = el . slotName
340- if ( seenSlots [ name ] ) {
341- warn (
342- `Duplicate ${ name ? `<slot> with name ${ name } ` : `default <slot>` } ` +
343- `found in the same template.`
344- )
345- }
346- seenSlots [ name ] = true
347- }
348328 } else {
349329 const slotTarget = getBindingAttr ( el , 'slot' )
350330 if ( slotTarget ) {
Original file line number Diff line number Diff line change @@ -36,13 +36,6 @@ export function renderMixin (Vue: Class<Component>) {
3636 _parentVnode
3737 } = vm . $options
3838
39- if ( vm . _isMounted ) {
40- // clone slot nodes on re-renders
41- for ( const key in vm . $slots ) {
42- vm . $slots [ key ] = cloneVNodes ( vm . $slots [ key ] )
43- }
44- }
45-
4639 if ( staticRenderFns && ! vm . _staticTrees ) {
4740 vm . _staticTrees = [ ]
4841 }
@@ -155,6 +148,30 @@ export function renderMixin (Vue: Class<Component>) {
155148 return ret
156149 }
157150
151+ // renderSlot
152+ Vue . prototype . _t = function (
153+ name : string ,
154+ fallback : ?Array < VNode >
155+ ) : ?Array < VNode > {
156+ let slotNodes = this . $slots [ name ]
157+ if ( slotNodes ) {
158+ // warn duplicate slot usage
159+ if ( process . env . NODE_ENV !== 'production' ) {
160+ slotNodes . _rendered && warn (
161+ `Duplicate presense of slot "${ name } " found in the same render tree ` +
162+ `- this will likely cause render errors.` ,
163+ this
164+ )
165+ slotNodes . _rendered = true
166+ }
167+ // clone slot nodes on re-renders
168+ if ( this . _isMounted ) {
169+ slotNodes = cloneVNodes ( slotNodes )
170+ }
171+ }
172+ return slotNodes || fallback
173+ }
174+
158175 // apply v-bind object
159176 Vue . prototype . _b = function bindProps (
160177 vnode : VNodeWithData ,
Original file line number Diff line number Diff line change @@ -458,28 +458,41 @@ describe('Component slot', () => {
458458 it ( 'warn duplicate slots' , ( ) => {
459459 new Vue ( {
460460 template : `<div>
461- <slot></slot><slot></slot>
462- <slot name="a"></slot><slot name="a"></slot>
463- </div>`
461+ <test>
462+ <div>foo</div>
463+ <div slot="a">bar</div>
464+ </test>
465+ </div>` ,
466+ components : {
467+ test : {
468+ template : `<div>
469+ <slot></slot><slot></slot>
470+ <div v-for="i in 3"><slot name="a"></slot></div>
471+ </div>`
472+ }
473+ }
464474 } ) . $mount ( )
465- expect ( 'Duplicate default < slot> ' ) . toHaveBeenWarned ( )
466- expect ( 'Duplicate <slot> with name "a"' ) . toHaveBeenWarned ( )
475+ expect ( 'Duplicate presense of slot "default" ' ) . toHaveBeenWarned ( )
476+ expect ( 'Duplicate presense of slot "a"' ) . toHaveBeenWarned ( )
467477 } )
468478
469- it ( 'warn static slot inside v-for' , ( ) => {
470- new Vue ( {
471- template : `<div>
472- <div v-for="i in 1"><slot :name="'test' + i"></slot></div>
473- </div>`
474- } ) . $mount ( )
475- expect ( 'Static <slot> found inside v-for' ) . not . toHaveBeenWarned ( )
476-
479+ it ( 'should not warn valid conditional slots' , ( ) => {
477480 new Vue ( {
478481 template : `<div>
479- <div v-for="i in 1"><slot></slot></div>
480- </div>`
482+ <test>
483+ <div>foo</div>
484+ </test>
485+ </div>` ,
486+ components : {
487+ test : {
488+ template : `<div>
489+ <slot v-if="true"></slot>
490+ <slot v-else></slot>
491+ </div>`
492+ }
493+ }
481494 } ) . $mount ( )
482- expect ( 'Static <slot> found inside v-for' ) . toHaveBeenWarned ( )
495+ expect ( 'Duplicate presense of slot "default"' ) . not . toHaveBeenWarned ( )
483496 } )
484497
485498 // #3518
Original file line number Diff line number Diff line change @@ -98,21 +98,21 @@ describe('codegen', () => {
9898 it ( 'generate single slot' , ( ) => {
9999 assertCodegen (
100100 '<slot></slot>' ,
101- `with(this){return $slots[ "default"] }`
101+ `with(this){return _t( "default") }`
102102 )
103103 } )
104104
105105 it ( 'generate named slot' , ( ) => {
106106 assertCodegen (
107107 '<slot name="one"></slot>' ,
108- `with(this){return $slots[ "one"] }`
108+ `with(this){return _t( "one") }`
109109 )
110110 } )
111111
112112 it ( 'generate slot fallback content' , ( ) => {
113113 assertCodegen (
114114 '<slot><div>hi</div></slot>' ,
115- `with(this){return ($slots[ "default"]|| [_m(0)])}` ,
115+ `with(this){return _t( "default", [_m(0)])}` ,
116116 [ `with(this){return _h('div',["hi"])}` ]
117117 )
118118 } )
You can’t perform that action at this time.
0 commit comments