Преглед изворни кода

support v-bind object on scoped slots (fix #4529)

Evan You пре 9 година
родитељ
комит
0eb8cdc7f7

+ 13 - 7
src/compiler/codegen/index.js

@@ -343,13 +343,19 @@ function genText (text: ASTText | ASTExpression): string {
 function genSlot (el: ASTElement): string {
   const slotName = el.slotName || '"default"'
   const children = genChildren(el)
-  return `_t(${slotName}${
-    children ? `,${children}` : ''
-  }${
-    el.attrs ? `${children ? '' : ',null'},{${
-      el.attrs.map(a => `${camelize(a.name)}:${a.value}`).join(',')
-    }}` : ''
-  })`
+  let res = `_t(${slotName}${children ? `,${children}` : ''}`
+  const attrs = el.attrs && `{${el.attrs.map(a => `${camelize(a.name)}:${a.value}`).join(',')}}`
+  const bind = el.attrsMap['v-bind']
+  if ((attrs || bind) && !children) {
+    res += `,null`
+  }
+  if (attrs) {
+    res += `,${attrs}`
+  }
+  if (bind) {
+    res += `${attrs ? '' : ',null'},${bind}`
+  }
+  return res + ')'
 }
 
 // componentName is el.component, take it as argument to shun flow's pessimistic refinement

+ 8 - 2
src/core/instance/render.js

@@ -9,6 +9,7 @@ import VNode, {
 } from '../vdom/vnode'
 import {
   warn,
+  extend,
   identity,
   isObject,
   toObject,
@@ -203,11 +204,16 @@ export function renderMixin (Vue: Class<Component>) {
   Vue.prototype._t = function (
     name: string,
     fallback: ?Array<VNode>,
-    props: ?Object
+    props: ?Object,
+    bindObject: ?Object
   ): ?Array<VNode> {
     const scopedSlotFn = this.$scopedSlots[name]
     if (scopedSlotFn) { // scoped slot
-      return scopedSlotFn(props || {}) || fallback
+      props = props || {}
+      if (bindObject) {
+        extend(props, bindObject)
+      }
+      return scopedSlotFn(props) || fallback
     } else {
       const slotNodes = this.$slots[name]
       // warn duplicate slot usage

+ 34 - 0
test/unit/features/component/component-scoped-slot.spec.js

@@ -31,6 +31,40 @@ describe('Component scoped slot', () => {
     }).then(done)
   })
 
+  it('with v-bind', done => {
+    const vm = new Vue({
+      template: `
+        <test ref="test">
+          <template scope="props">
+            <span>{{ props.msg }} {{ props.msg2 }}</span>
+          </template>
+        </test>
+      `,
+      components: {
+        test: {
+          data () {
+            return {
+              msg: 'hello',
+              obj: { msg2: 'world' }
+            }
+          },
+          template: `
+            <div>
+              <slot :msg="msg" v-bind="obj"></slot>
+            </div>
+          `
+        }
+      }
+    }).$mount()
+
+    expect(vm.$el.innerHTML).toBe('<span>hello world</span>')
+    vm.$refs.test.msg = 'bye'
+    vm.$refs.test.obj.msg2 = 'bye'
+    waitForUpdate(() => {
+      expect(vm.$el.innerHTML).toBe('<span>bye bye</span>')
+    }).then(done)
+  })
+
   it('template slot', done => {
     const vm = new Vue({
       template: `