vue的prop里的type类型除了用来校验类型外,还会影响接收的值吗?

595 阅读2分钟

0.先抛出个问题

vue的prop里的type类型除了用来校验类型外,还会影响接收的值吗?

举个例子

<template>
    <div>
        flag:{{flag}}
    </div>
</template>

<script>
export default {
    props: {
        flag: {
            type: Boolean,
            // type: [String, Boolean],
        }
    }
}
</script>

这里接收的flagtype类型定义为 Boolean和定义为[String, Boolean]或者不定义type,会对接收的flag值有影响吗?(文章末尾给答案)

1.背景

前几天,在项目中碰到一个props传值问题。

父组件

<template>
   // 实际项目上,flag值通过一些逻辑计算获得的(这里为了方便,写成空字符串)
   <SubComponentVue flag=""/>
</template>

<script>
import SubComponentVue from "../components/SubComponent.vue"
export default {
    components: {
        SubComponentVue
    }
}
</script>

子组件

<template>
    <div>
        // 子组件用 flag 做一些逻辑判断
        flag:{{flag}}
    </div>
</template>

<script>
export default {
    props: {
        flag: {
            type: Boolean,
        }
    }
}
</script>

此时子组件props接收的 flag 的值是多少呢? 相信很多小伙伴会回答是 空字符串false。 实际上是 true,想不到吧🙈

2. 查看vue源码是如何处理prop

带着上面的疑惑,查看了下vue(2.6.11)源码是如何处理prop的

export function validateProp (
  key: string,
  propOptions: Object,
  propsData: Object,
  vm?: Component
): any {
  const prop = propOptions[key]
  const absent = !hasOwn(propsData, key)
  let value = propsData[key]
  // 检测type里有没有定义Boolean类型
  const booleanIndex = getTypeIndex(Boolean, prop.type)
  // 如果检测到type里有定义Boolean类型,走if里面逻辑
  if (booleanIndex > -1) {
    if (absent && !hasOwn(prop, 'default')) {
      // 父组件没传值 且 没定义默认值,返回false
      value = false
    } else if (value === '' || value === hyphenate(key)) {
       // 父组件传''空字符串 
       // 或者 以<SubComponentVue flag/>这种方式传 ,
      const stringIndex = getTypeIndex(String, prop.type)
      // 考虑type有传多个值的情况:
      // 如果不包含String类型,则返回true
      // 如果包含String类型, 但 Boolean类型在String类型的前面,也返回true. 比如:type: [Boolean, String],
      if (stringIndex < 0 || booleanIndex < stringIndex) {
        value = true
      }
    }
  }
  // 以上情况都不满足时,如果父组件没传值,取默认值
  if (value === undefined) {
    value = getPropDefaultValue(vm, prop, key)
    // since the default value is a fresh copy,
    // make sure to observe it.
    const prevShouldObserve = shouldObserve
    toggleObserving(true)
    observe(value)
    toggleObserving(prevShouldObserve)
  }
  if (
    process.env.NODE_ENV !== 'production' &&
    // skip validation for weex recycle-list child component props
    !(__WEEX__ && isObject(value) && ('@binding' in value))
  ) {
    assertProp(prop, key, value, vm, absent)
  }
  // 以上情况都不满足时,取父组件传的值
  return value
}

发现vue源码里对type为Boolean类型做了特殊处理(具体分析注释在上面的代码里)。

3. 先回答下文章开头的问题:

vue的prop里的type类型除了用来校验类型外,还会影响接收的值吗?

答案是:

4. 总结

prop传值问题

    1. 如果子组件props接收的type包含Boolean类型,
      • 1.1 父组件没传值没定义默认值,返回false
      • 1.2 父组件传''空字符串 或者 以<SubComponentVue flag/>这种方式传
        • 1.2.1 如果不包含String类型,则返回true.
        • 1.2.2 如果包含String类型, 但 Boolean类型在String类型的前面,也返回true. 比如:type: [Boolean, String]
    1. 以上的条件不满足时,则父组件传什么值,子组件就会接收什么值。父组件不传值,子组件就取default默认值, 没有定义默认值的话,返回undefined