Vue3中如何判断组件的prop是否为父组件显式传入
Vue3如何区分prop是父组件显式传入还是使用默认值
核心实现思路
Vue3移除了Vue2的$options.propsData API,我们可以通过当前组件VNode上挂载的原始传入属性集合判断,该集合仅包含父组件实际传递的属性,不包含使用默认值补全的prop。
具体实现方案
方案1:基于组件实例VNode判断(推荐)
组合式API写法
<script setup> import { getCurrentInstance } from 'vue' // 声明带默认值的prop const props = defineProps({ name: { type: String, default: 'Friend' } }) // 获取当前组件实例 const instance = getCurrentInstance() // 父组件实际传入的所有属性集合 const passedProps = instance.vnode.props // 判断name是否为显式传入 const isNameExplicitlyPassed = Reflect.has(passedProps, 'name') // 父组件调用<Greeting name="Friend" />时返回true,调用<Greeting />时返回false </script>
选项式API写法
export default { props: { name: { type: String, default: 'Friend' } }, mounted() { // 获取父组件实际传入的属性集合 const passedProps = this.$.vnode.props const isNameExplicitlyPassed = Reflect.has(passedProps, 'name') console.log(isNameExplicitlyPassed) } }
方案2:默认值打标法(轻量场景适用)
如果不想依赖组件内部实例,也可以在默认值工厂函数中为默认值加特殊标记,后续通过标记判断:
<script setup> import { computed } from 'vue' const props = defineProps({ name: { type: [String, Object], default: () => ({ __isDefault: true, value: 'Friend' }) } }) // 处理为实际业务使用的name值 const name = computed(() => { if (typeof props.name === 'object' && props.name?.__isDefault) { return props.name.value } return props.name }) // 判断是否使用了默认值 const usedDefault = typeof props.name === 'object' && props.name?.__isDefault </script>
注意:该方案需要调整prop的类型声明,且要避免父组件传入带
__isDefault标记的同名属性,否则会出现误判。
注意事项
getCurrentInstance仅能在setup函数或组件生命周期钩子中同步调用,异步回调中调用可能无法拿到实例。- 模板中使用kebab-case命名的prop,Vue会自动转为camelCase存储在
vnode.props中,直接用prop声明的camelCase名称判断即可。
内容的提问来源于stack exchange,提问作者supertrue
相关产品推荐
相关产品推荐

