Browse Source

adjust render fn + fix props validation for functional components

Evan You 9 years ago
parent
commit
03621ee245

+ 1 - 1
src/core/instance/lifecycle.js

@@ -118,7 +118,7 @@ export function lifecycleMixin (Vue: Class<Component>) {
       const propKeys = vm.$options._propKeys || []
       for (let i = 0; i < propKeys.length; i++) {
         const key = propKeys[i]
-        vm[key] = validateProp(vm, key, propsData)
+        vm[key] = validateProp(key, vm.$options.props, propsData, vm)
       }
       observerState.shouldConvert = true
       if (process.env.NODE_ENV !== 'production') {

+ 2 - 2
src/core/instance/state.js

@@ -40,7 +40,7 @@ function initProps (vm: Component) {
       const key = keys[i]
       /* istanbul ignore else */
       if (process.env.NODE_ENV !== 'production') {
-        defineReactive(vm, key, validateProp(vm, key, propsData), () => {
+        defineReactive(vm, key, validateProp(key, props, propsData, vm), () => {
           if (vm.$parent && !observerState.isSettingProps) {
             warn(
               `Avoid mutating a prop directly since the value will be ` +
@@ -52,7 +52,7 @@ function initProps (vm: Component) {
           }
         })
       } else {
-        defineReactive(vm, key, validateProp(vm, key, propsData))
+        defineReactive(vm, key, validateProp(key, props, propsData, vm))
       }
     }
     observerState.shouldConvert = true

+ 10 - 5
src/core/util/props.js

@@ -11,10 +11,15 @@ type PropOptions = {
   validator: ?Function
 }
 
-export function validateProp (vm: Component, key: string, propsData: ?Object): any {
+export function validateProp (
+  key: string,
+  propOptions: Object,
+  propsData: ?Object,
+  vm?: Component
+): any {
   /* istanbul ignore if */
-  if (!vm.$options.props || !propsData) return
-  const prop = vm.$options.props[key]
+  if (!propsData) return
+  const prop = propOptions[key]
   const absent = !hasOwn(propsData, key)
   let value = propsData[key]
   // handle boolean props
@@ -43,7 +48,7 @@ export function validateProp (vm: Component, key: string, propsData: ?Object): a
 /**
  * Get the default value of a prop.
  */
-function getPropDefaultValue (vm: Component, prop: PropOptions, name: string): any {
+function getPropDefaultValue (vm: ?Component, prop: PropOptions, name: string): any {
   // no default, return undefined
   if (!hasOwn(prop, 'default')) {
     return undefined
@@ -71,7 +76,7 @@ function assertProp (
   prop: PropOptions,
   name: string,
   value: any,
-  vm: Component,
+  vm: ?Component,
   absent: boolean
 ) {
   if (prop.required && absent) {

+ 10 - 5
src/core/vdom/create-component.js

@@ -4,7 +4,7 @@ import Vue from '../instance/index'
 import VNode from './vnode'
 import { normalizeChildren } from './helpers'
 import { callHook } from '../instance/lifecycle'
-import { warn, isObject, hasOwn, hyphenate } from '../util/index'
+import { warn, isObject, hasOwn, hyphenate, validateProp } from '../util/index'
 
 const hooks = { init, prepatch, insert, destroy }
 const hooksToMerge = Object.keys(hooks)
@@ -69,12 +69,17 @@ export function createComponent (
 
   // functional component
   if (Ctor.options.functional) {
+    const props = {}
+    const propOptions = Ctor.options.props
+    if (propOptions) {
+      Object.keys(propOptions).forEach(key => {
+        props[key] = validateProp(key, propOptions, propsData)
+      })
+    }
     return Ctor.options.render.call(
       null,
-      parent.$createElement,       // h
-      propsData || {},             // props
-      normalizeChildren(children), // children
-      data                         // data
+      parent.$createElement,
+      { props, parent, data, children: normalizeChildren(children) }
     )
   }
 

+ 2 - 2
test/unit/features/options/functional.spec.js

@@ -9,7 +9,7 @@ describe('Options functional', () => {
         wrap: {
           functional: true,
           props: ['msg'],
-          render (h, props, children) {
+          render (h, { props, children }) {
             return h('div', null, [props.msg, ' '].concat(children))
           }
         }
@@ -35,7 +35,7 @@ describe('Options functional', () => {
         validate: {
           functional: true,
           props: ['field'],
-          render (h, props, children, { on }) {
+          render (h, { props, children, data: { on } }) {
             props.child = children[0]
             return h('validate-control', { props, on })
           }