荣耀文档
80.56M · 2026-04-14
在 Vue3 迁移 React、跨框架组件封装的场景里,透传 Attributes 是几乎必用、但极易踩坑的能力。Vue 的 $attrs / useAttrs 和 React 的 props 体系设计差异很大,而 VuReact 作为稳定的 Vue3 → React 编译工具,已经把这套逻辑做了完整对齐。
本文带你一次性搞懂:透传属性是什么、为什么必须用 useAttrs、TS 怎么写、转换后长什么样,直接复制就能用。
透传 attribute:传给组件,但没有被声明为 props / emits 的属性或事件器。
最常见:class、style、id、自定义属性、v-on 等。
Vue 默认会把它们自动继承到组件根节点,也可以用 $attrs 或 useAttrs() 手动控制。
React 没有“透传”这个名词,但行为一致:
所有没在 Props 里定义的属性,都属于“透传属性”,全部挂在 props 上。
区别是:
VuReact 把透传属性统一理解为: 无类型约束的运行时对象 + 已声明 Props 合并 = 最终组件属性
props: Record<string, unknown>Props & Record<string, unknown>$attrs 转向 useAttrs()Vue 里有两种写法:
$attrs:运行时隐式变量 → VuReact 无法静态分析useAttrs():显式 API → VuReact 完美支持、推荐唯一写法<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>
好处:
| Vue useAttrs 写法 | React 转换结果 |
|---|---|
| 无类型 | const attrs = props as Record<string, unknown> |
类型断言 as Attrs | const attrs = props as Attrs |
变量带类型 attrs: Attrs | const attrs = props as Attrs |
| 搭配 defineProps | Props & Record<string, unknown> |
Vue 输入
<template>
<div :class="attrs.class" :style="attrs.style">
{{ attrs.title }}
</div>
</template>
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>
React 输出
import { memo } from 'react'
const Comp = memo((props: Record<string, unknown>) => {
const attrs = props as Record<string, unknown>
return (
<div className={attrs.class} style={attrs.style}>
{attrs.title}
</div>
)
})
export default Comp
Vue 输入
<template>
<div :class="attrs.class" :style="attrs.style">
{{ attrs.customTitle }}
</div>
</template>
<script setup lang="ts">
import { useAttrs } from 'vue'
interface CustomAttrs {
class?: string
style?: React.CSSProperties
customTitle?: string
[key: string]: unknown
}
const props = defineProps<{
id: string
}>()
const attrs = useAttrs() as CustomAttrs
</script>
React 输出
import { memo } from 'react'
interface CustomAttrs {
class?: string
style?: React.CSSProperties
customTitle?: string
[key: string]: unknown
}
type ICompProps = { id: string }
const Comp = memo((props: ICompProps & Record<string, unknown>) => {
const attrs = props as CustomAttrs
return (
<div className={attrs.class} style={attrs.style}>
{attrs.customTitle}
</div>
)
})
export default Comp
Vue 输入
<template>
<div
:class="[
'base',
attrs.class,
attrs.xx?.class,
attrs['custom-class']
]"
>
{{ attrs?.xxx?.content }}
</div>
</template>
React 输出
import { memo } from 'react'
import { dir } from '@vureact/runtime-core'
const Comp = memo((props: Record<string, unknown>) => {
const attrs = props
return (
<div
className={dir.cls([
'base',
attrs.class,
attrs.xx?.class,
attrs['custom-class']
])}
>
{attrs?.xxx?.content}
</div>
)
})
必须用 useAttrs(),禁止用 $attrs 编译器无法分析运行时变量,会丢属性。
TS 尽量写接口 有利于提示、重构、避免空值报错。
class/style 自动适配
class → className
style → 自动适配 React.CSSProperties
defineProps + useAttrs 会自动合并类型 不用手动改。
JS 项目直接用
会被编译成 const attrs = props,完全兼容。
VuReact 处理透传 Attributes 的核心思想只有一句话: 把 Vue 隐式的 $attrs 变成显式的 useAttrs,再映射到 React 的 props 体系。
正在做 Vue3 → React 迁移的同学,这套透传方案可以直接进团队规范。
#Vue3 #React #Vue转React #VuReact #前端迁移 #useAttrs #组件封装 #TypeScript