From abfa6fb3a485368ad1bcc39eac4eefa82f199705 Mon Sep 17 00:00:00 2001 From: liximomo <lixi@mufengcm.com> Date: Thu, 26 Jul 2018 21:25:53 +0800 Subject: [PATCH 1/4] fix(compiler): normalize nested arrays when use functional components with v-for #8468 --- src/compiler/codegen/index.js | 4 +++- test/unit/features/options/functional.spec.js | 21 +++++++++++++++++++ test/unit/modules/compiler/codegen.spec.js | 14 ++++++------- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index 1c912c4d96f..2c96e61a6e9 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -389,7 +389,9 @@ export function genChildren ( el.tag !== 'template' && el.tag !== 'slot' ) { - return (altGenElement || genElement)(el, state) + // because el may be a functional component and return an Array instead of a single root. + // In this case, just a simple normalization is needed + return `${(altGenElement || genElement)(el, state)},1` } const normalizationType = checkSkip ? getNormalizationType(children, state.maybeComponent) diff --git a/test/unit/features/options/functional.spec.js b/test/unit/features/options/functional.spec.js index 2c6abe95972..46100af83db 100644 --- a/test/unit/features/options/functional.spec.js +++ b/test/unit/features/options/functional.spec.js @@ -316,4 +316,25 @@ describe('Options functional', () => { triggerEvent(parent.$el.querySelector('.clickable'), 'click') waitForUpdate(assertMarkup).then(done) }) + + // #8468 + it('should normalize nested arrays when use functional components with v-for', () => { + const Foo = { + functional: true, + props: { + name: {} + }, + render (h, context) { + return [h('span', 'hi'), h('span', context.props.name)] + } + } + const vm = new Vue({ + template: `<div><foo v-for="name in names" :name="name" /></div>`, + data: { + names: ['foo', 'bar'] + }, + components: { Foo } + }).$mount() + expect(vm.$el.innerHTML).toBe('<span>hi</span><span>foo</span><span>hi</span><span>bar</span>') + }) }) diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js index 93a27f3b245..8a8f202f1df 100644 --- a/test/unit/modules/compiler/codegen.spec.js +++ b/test/unit/modules/compiler/codegen.spec.js @@ -54,25 +54,25 @@ describe('codegen', () => { it('generate v-for directive', () => { assertCodegen( '<div><li v-for="item in items" :key="item.uid"></li></div>', - `with(this){return _c('div',_l((items),function(item){return _c('li',{key:item.uid})}))}` + `with(this){return _c('div',_l((items),function(item){return _c('li',{key:item.uid})}),1)}` ) // iterator syntax assertCodegen( '<div><li v-for="(item, i) in items"></li></div>', - `with(this){return _c('div',_l((items),function(item,i){return _c('li')}))}` + `with(this){return _c('div',_l((items),function(item,i){return _c('li')}),1)}` ) assertCodegen( '<div><li v-for="(item, key, index) in items"></li></div>', - `with(this){return _c('div',_l((items),function(item,key,index){return _c('li')}))}` + `with(this){return _c('div',_l((items),function(item,key,index){return _c('li')}),1)}` ) // destructuring assertCodegen( '<div><li v-for="{ a, b } in items"></li></div>', - `with(this){return _c('div',_l((items),function({ a, b }){return _c('li')}))}` + `with(this){return _c('div',_l((items),function({ a, b }){return _c('li')}),1)}` ) assertCodegen( '<div><li v-for="({ a, b }, key, index) in items"></li></div>', - `with(this){return _c('div',_l((items),function({ a, b },key,index){return _c('li')}))}` + `with(this){return _c('div',_l((items),function({ a, b },key,index){return _c('li')}),1)}` ) // v-for with extra element assertCodegen( @@ -126,7 +126,7 @@ describe('codegen', () => { it('generate ref on v-for', () => { assertCodegen( '<ul><li v-for="item in items" ref="component1"></li></ul>', - `with(this){return _c('ul',_l((items),function(item){return _c('li',{ref:"component1",refInFor:true})}))}` + `with(this){return _c('ul',_l((items),function(item){return _c('li',{ref:"component1",refInFor:true})}),1)}` ) }) @@ -550,7 +550,7 @@ describe('codegen', () => { it('generate static trees inside v-for', () => { assertCodegen( `<div><div v-for="i in 10"><p><span></span></p></div></div>`, - `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}))}`, + `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}),1)}`, [`with(this){return _c('p',[_c('span')])}`] ) }) From 0c9b3958bbbf2d222b65d18076e42f875355daa3 Mon Sep 17 00:00:00 2001 From: Evan You <yyx990803@gmail.com> Date: Tue, 23 Oct 2018 16:12:18 -0400 Subject: [PATCH 2/4] Update index.js --- src/compiler/codegen/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index 2c96e61a6e9..b1c4116696d 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -391,7 +391,8 @@ export function genChildren ( ) { // because el may be a functional component and return an Array instead of a single root. // In this case, just a simple normalization is needed - return `${(altGenElement || genElement)(el, state)},1` + const normalizationType = state.maybeComponent(el) ? `,1` : `` + return `${(altGenElement || genElement)(el, state)}${normalizationType}` } const normalizationType = checkSkip ? getNormalizationType(children, state.maybeComponent) From 5604ef1b87e3a2a72ae25aa55da96a5196bcde8b Mon Sep 17 00:00:00 2001 From: Evan You <yyx990803@gmail.com> Date: Wed, 24 Oct 2018 14:01:26 -0400 Subject: [PATCH 3/4] Update codegen.spec.js --- test/unit/modules/compiler/codegen.spec.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js index 8a8f202f1df..14ad1d48287 100644 --- a/test/unit/modules/compiler/codegen.spec.js +++ b/test/unit/modules/compiler/codegen.spec.js @@ -54,25 +54,25 @@ describe('codegen', () => { it('generate v-for directive', () => { assertCodegen( '<div><li v-for="item in items" :key="item.uid"></li></div>', - `with(this){return _c('div',_l((items),function(item){return _c('li',{key:item.uid})}),1)}` + `with(this){return _c('div',_l((items),function(item){return _c('li',{key:item.uid})}))}` ) // iterator syntax assertCodegen( '<div><li v-for="(item, i) in items"></li></div>', - `with(this){return _c('div',_l((items),function(item,i){return _c('li')}),1)}` + `with(this){return _c('div',_l((items),function(item,i){return _c('li')}))}` ) assertCodegen( '<div><li v-for="(item, key, index) in items"></li></div>', - `with(this){return _c('div',_l((items),function(item,key,index){return _c('li')}),1)}` + `with(this){return _c('div',_l((items),function(item,key,index){return _c('li')}))}` ) // destructuring assertCodegen( '<div><li v-for="{ a, b } in items"></li></div>', - `with(this){return _c('div',_l((items),function({ a, b }){return _c('li')}),1)}` + `with(this){return _c('div',_l((items),function({ a, b }){return _c('li')}))}` ) assertCodegen( '<div><li v-for="({ a, b }, key, index) in items"></li></div>', - `with(this){return _c('div',_l((items),function({ a, b },key,index){return _c('li')}),1)}` + `with(this){return _c('div',_l((items),function({ a, b },key,index){return _c('li')}))}` ) // v-for with extra element assertCodegen( @@ -126,7 +126,7 @@ describe('codegen', () => { it('generate ref on v-for', () => { assertCodegen( '<ul><li v-for="item in items" ref="component1"></li></ul>', - `with(this){return _c('ul',_l((items),function(item){return _c('li',{ref:"component1",refInFor:true})}),1)}` + `with(this){return _c('ul',_l((items),function(item){return _c('li',{ref:"component1",refInFor:true})}))}` ) }) From 63012f8074469579d28399e54750be11744e6cef Mon Sep 17 00:00:00 2001 From: Evan You <yyx990803@gmail.com> Date: Wed, 24 Oct 2018 14:01:55 -0400 Subject: [PATCH 4/4] Update codegen.spec.js --- test/unit/modules/compiler/codegen.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js index 14ad1d48287..93a27f3b245 100644 --- a/test/unit/modules/compiler/codegen.spec.js +++ b/test/unit/modules/compiler/codegen.spec.js @@ -550,7 +550,7 @@ describe('codegen', () => { it('generate static trees inside v-for', () => { assertCodegen( `<div><div v-for="i in 10"><p><span></span></p></div></div>`, - `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}),1)}`, + `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}))}`, [`with(this){return _c('p',[_c('span')])}`] ) })