Vue3+TypeScript中如何正确切换布尔Prop实现失焦验证?
解决Vue3+TS中修改Prop报错的问题及邮箱验证优化
问题原因
你遇到的报错是因为Vue的Prop是只读属性,子组件不能直接修改父组件传递过来的Prop,必须遵循单向数据流规则。而且这里的focused状态属于组件内部的交互状态,根本不需要定义成Prop,应该用组件自身的响应式变量来管理。
正确解决方案
我们把内部状态改成Vue的ref变量,用来标记输入框是否已经失焦,再结合CSS和输入框的验证状态来控制错误提示的显示:
修改后的完整代码
<template> <div class="email-input-wrapper"> <input class="appearance-none bg-transparent border-disabled rounded-lg w-full py-3 px-4 col-span-2 text-secondary focus:outline-none focus:bg-white focus:border-pink focus:ring-0" type="email" :placeholder="t('contact.email')" v-model="email" @blur="isTouched = true" required pattern="^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" /> <span class="triggerError"> It should be a valid email address! </span> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue' import axios from 'axios' import { useReCaptcha } from 'vue-recaptcha-v3' import { useI18n } from 'vue-i18n' export default defineComponent({ name: 'Form', setup() { const email = ref('') const isTouched = ref(false) const { t } = useI18n() // 其他业务逻辑... return { email, isTouched, t } } }) </script> <style scoped> .triggerError { color: red; display: none; } /* 失焦后输入无效时显示错误提示 */ input.touched:invalid ~ .triggerError { display: block; } /* 可选:给失焦后无效的输入框加样式提示 */ input.touched:invalid { border-color: #ff4d4f; } </style>
关键调整点
- 移除了原来的
focusedProp,改用内部的isTouched响应式变量,记录输入框是否已被触碰(失焦) - 失焦事件
@blur直接把isTouched设为true(只要失焦过一次,就应该触发验证提示,不需要切换状态) - 给输入框动态绑定
touched类:<input :class="{ touched: isTouched }" ... />,让CSS可以精准匹配状态 - CSS通过
input.touched:invalid ~ .triggerError选择器,仅在输入框失焦且内容不符合规则时显示错误提示
特殊场景处理
如果这个状态确实需要和父组件同步(比如父组件要感知输入框的失焦状态),可以通过自定义事件实现双向绑定:
- 子组件触发事件:
@blur="$emit('update:focused', true)" - 父组件用
v-model:focused="parentFocused"绑定状态
但在你的邮箱验证场景里,这个状态完全是子组件内部使用的,用内部ref是最优解。
内容的提问来源于stack exchange,提问作者Tomas Gil Amoedo
相关产品推荐
相关产品推荐

