Vue组件如何实现多Props二选一必填?且禁止同时传入?
Vue组件实现「url/text二选一且不能同时传」的Prop校验方案
嘿,这个需求用Vue的自定义Prop校验函数就能完美搞定!正好能满足你“必须传其中一个,且不能同时传”的要求,我给你一步步拆解:
第一步:实现「必须传入其中一个」的校验
Vue内置的required和type没法处理这种互斥的必填逻辑,所以我们要给每个Prop写自定义校验函数,确保当当前Prop没传时,另一个Prop必须存在:
export default { props: { url: { type: String, validator(value) { // 规则:如果url没传,text必须传;url传了就没问题 return value !== undefined || this.text !== undefined } }, text: { type: String, validator(value) { // 规则:如果text没传,url必须传;text传了就没问题 return value !== undefined || this.url !== undefined } } } }
这里的validator函数里,this指向组件实例,所以能直接访问到另一个Prop的值。开发模式下,如果两个Prop都没传,Vue会自动抛出Prop校验失败的警告。
第二步:加上「禁止同时传入两者」的限制
如果要严格限制只能传其中一个,不能同时传,只需要修改校验逻辑,确保要么url存在text不存在,要么text存在url不存在:
export default { props: { url: { type: String, validator(value) { const hasUrl = value !== undefined const hasText = this.text !== undefined // 两种合法情况:二选一 return (hasUrl && !hasText) || (!hasUrl && hasText) } }, text: { type: String, validator(value) { const hasText = value !== undefined const hasUrl = this.url !== undefined return (hasText && !hasUrl) || (!hasText && hasUrl) } } } }
这样一来,不管是两个都不传,还是两个都传,都会触发Prop校验警告,完美符合你的需求!
额外:组件内部渲染逻辑
最后补充一下组件内部的渲染,根据传入的Prop决定渲染<a>还是<span>:
<template> <div> <a v-if="url" :href="url">{{ text || url }}</a> <span v-else>{{ text }}</span> </div> </template> <script> export default { props: { /* 上面的校验规则 */ }, // 也可以用计算属性统一处理显示内容 computed: { displayContent() { return this.text || this.url } } } </script>
针对Vue 3组合式API的补充
如果是用Vue 3的<script setup>,因为defineProps的校验函数无法直接访问其他Prop,我们可以在组件挂载时手动做校验:
<script setup> import { onMounted } from 'vue' const props = defineProps({ url: String, text: String }) onMounted(() => { const hasUrl = props.url !== undefined && props.url.trim() !== '' const hasText = props.text !== undefined && props.text.trim() !== '' if (!hasUrl && !hasText) { console.error('[你的组件名]:必须传入url或text其中一个!') } if (hasUrl && hasText) { console.error('[你的组件名]:不能同时传入url和text!') } }) </script>
这种方式是运行时校验,在开发模式下会输出错误提示,也能达到同样的效果。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

