Browse Source

fix(compiler): normalize potential functional component children in v-for (#8558)

fix #8468
X.L 7 years ago
parent
commit
d483a49c86
2 changed files with 25 additions and 1 deletions
  1. 4 1
      src/compiler/codegen/index.js
  2. 21 0
      test/unit/features/options/functional.spec.js

+ 4 - 1
src/compiler/codegen/index.js

@@ -406,7 +406,10 @@ 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
+      const normalizationType = state.maybeComponent(el) ? `,1` : ``
+      return `${(altGenElement || genElement)(el, state)}${normalizationType}`
     }
     const normalizationType = checkSkip
       ? getNormalizationType(children, state.maybeComponent)

+ 21 - 0
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>')
+  })
 })