Jelajahi Sumber

pass vnode raw data in functional component (#3168)

kazuya kawaguchi 10 tahun lalu
induk
melakukan
c665a682d2

+ 4 - 3
src/core/vdom/create-component.js

@@ -71,9 +71,10 @@ export function createComponent (
   if (Ctor.options.functional) {
     return Ctor.options.render.call(
       null,
-      parent.$createElement,      // h
-      propsData || {},            // props
-      normalizeChildren(children) // children
+      parent.$createElement,       // h
+      propsData || {},             // props
+      normalizeChildren(children), // children
+      data                         // data
     )
   }
 

+ 59 - 0
test/unit/features/options/functional.spec.js

@@ -21,4 +21,63 @@ describe('Options functional', () => {
       expect(vm.$el.innerHTML).toBe('<div>qux bar</div>')
     }).then(done)
   })
+
+  it('should let vnode raw data pass through', done => {
+    const onValid = jasmine.createSpy('valid')
+    const vm = new Vue({
+      data: { msg: 'hello' },
+      template: `<div>
+        <validate field="field1" @valid="onValid">
+          <input type="text" v-model="msg">
+        </validate>
+      </div>`,
+      components: {
+        validate: {
+          functional: true,
+          props: ['field'],
+          render (h, props, children, { on }) {
+            props.child = children[0]
+            return h('validate-control', { props, on })
+          }
+        },
+        'validate-control': {
+          props: ['field', 'child'],
+          render () {
+            return this.child
+          },
+          mounted () {
+            this.$el.addEventListener('input', this.onInput)
+          },
+          destroyed () {
+            this.$el.removeEventListener('input', this.onInput)
+          },
+          methods: {
+            onInput (e) {
+              const value = e.target.value
+              if (this.validate(value)) {
+                this.$emit('valid', this)
+              }
+            },
+            // something validation logic here
+            validate (val) {
+              return val.length > 0
+            }
+          }
+        }
+      },
+      methods: { onValid }
+    }).$mount()
+    document.body.appendChild(vm.$el)
+    const input = vm.$el.querySelector('input')
+    expect(onValid).not.toHaveBeenCalled()
+    waitForUpdate(() => {
+      input.value = 'foo'
+      triggerEvent(input, 'input')
+    }).then(() => {
+      expect(onValid).toHaveBeenCalled()
+    }).then(() => {
+      document.body.removeChild(vm.$el)
+      vm.$destroy()
+    }).then(done)
+  })
 })