ref 不用于定义 props 类型,props 类型必须通过 defineprops 声明;ref 用于创建响应式变量,可封装基于 props 派生的状态,但需注意 props 的只读性及 ref 的类型标注准确性。

Vue 3 的 ref 本身不用于定义 Props 类型——Props 类型必须通过 defineProps 声明,而 ref 是用来创建响应式变量的。两者职责不同,但可以协同使用:Props 提供输入数据,ref(或 reactive)常用于封装基于 Props 派生的状态或本地状态。
Props 类型必须用 defineProps 声明
Vue 3 组合式 API 中,Props 的类型约束只能通过 defineProps 实现,不能靠 ref 替代。它支持两种主流写法:
-
泛型接口方式(推荐):类型清晰、可复用、IDE 支持好
interface User { id: number; name: string }const props = defineProps() -
运行时 + 类型断言方式:兼容需要运行时校验的场景
import type { PropType } from 'vue'const props = defineProps({ user: { type: Object as PropType<user>, required: true } })</user>
ref 可以包装 Props 衍生值,但需注意只读性
Props 是只读的(readonly),直接对 props.xxx 赋值会报错。若需可修改副本,应显式用 ref 创建新响应式变量:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 基础类型可直接解构 + ref:
const count = ref(props.initialCount) - 对象类型建议用
structuredClone或展开避免响应式污染:const editableUser = ref({ ...props.user }) - 不要写
const userRef = ref(props.user)—— 这会让userRef.value仍指向只读对象,后续赋值会失败
复杂 Props 场景下 ref 的类型标注技巧
当 ref 存储的数据结构与 Props 高度相关时,应复用已有接口,保持类型一致性:
- 用同一接口定义 Props 和 ref:
interface FormConfig { fields: string[]; submitUrl: string }const props = defineProps()const localConfig = ref<formconfig>(structuredClone(props.config))</formconfig> - 处理可能为 undefined 的 Props:
const props = defineProps()const avatarUrl = ref<string null>(props.avatar ?? null)</string> - 函数类型 Props 配合 ref 存储回调:
const props = defineProps void }>()const submitHandler = ref<typeof props.onsubmit>(props.onSubmit)</typeof>
常见误区提醒
以下做法容易引发类型错误或运行时问题:
- 误以为
ref(props.xxx)能“增强”Props 类型 —— 实际上它只是创建新引用,不改变 Props 本身的只读性 - 未标注泛型就初始化 ref:
const name = ref('') → 推断为 ref<string></string>没问题,但const user = ref({})会推断为ref<record any>></record>,丢失类型信息 - 在
defineProps中混用import { PropType }和import type { PropType }导致 TS 报错,应统一用import type(尤其开启isolatedModules: true时)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










