Vue3 转 React:组件透传 Attributes 与 useAttrs 使用详解|VuReact 实战

在 Vue3 迁移 React、跨框架组件封装的场景里,透传 Attributes 是几乎必用、但极易踩坑的能力。Vue 的 $attrs / useAttrs 和 React 的 props 体系设计差异很大,而 VuReact 作为稳定的 Vue3 → React 编译工具,已经把这套逻辑做了完整对齐。

本文带你一次性搞懂:透传属性是什么、为什么必须用 useAttrs、TS 怎么写、转换后长什么样,直接复制就能用。


一、先搞懂:透传 Attributes 到底是什么?

1. Vue 官方定义

透传 attribute :传给组件,但没有被声明为 props / emits 的属性或事件监听器。 最常见:class、style、id、自定义属性、v-on 监听等。

Vue 默认会把它们自动继承到组件根节点 ,也可以用 $attrs 或 useAttrs() 手动控制。

2. React 里的等价逻辑

React 没有"透传"这个名词,但行为一致: 所有没在 Props 里定义的属性,都属于"透传属性" ,全部挂在 props 上。

区别是:

  • Vue:运行时自动处理
  • React + TS:必须显式写类型,否则报错

3. VuReact 的核心适配规则

VuReact 把透传属性统一理解为: 无类型约束的运行时对象 + 已声明 Props 合并 = 最终组件属性

  • 组件无 Props → 自动生成:props: Record<string, unknown>
  • 组件有 Props → 自动交叉类型:Props & Record<string, unknown>

二、关键:必须从 $attrs 转向 useAttrs()

Vue 里有两种写法:

  • $attrs:运行时隐式变量 → VuReact 无法静态分析
  • useAttrs():显式 API → VuReact 完美支持、推荐唯一写法

1. Vue 中标准 useAttrs 写法(必背)

html 复制代码
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>

好处:

  • 编译器可静态识别
  • 支持 TS 类型注解
  • 符合 React"显式优于隐式"的习惯

2. VuReact 转换规则(一张表看懂)

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 到 React 完整对照

示例 1:基础用法(无 TS)

Vue 输入

html 复制代码
<template>
  <div :class="attrs.class" :style="attrs.style">
    {{ attrs.title }}
  </div>
</template>

<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>

React 输出

tsx 复制代码
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

示例 2:TS 类型增强(企业级推荐)

Vue 输入

html 复制代码
<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 输出

tsx 复制代码
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

示例 3:动态属性 / 可选链(真实业务常用)

Vue 输入

html 复制代码
<template>
  <div
    :class="[
      'base',
      attrs.class,
      attrs.xx?.class,
      attrs['custom-class']
    ]"
  >
    {{ attrs?.xxx?.content }}
  </div>
</template>

React 输出

tsx 复制代码
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>
  )
})

四、避坑指南(VuReact 必看)

  1. 必须用 useAttrs(),禁止用 $attrs 编译器无法分析运行时变量,会丢属性。

  2. TS 尽量写接口 有利于提示、重构、避免空值报错。

  3. class/style 自动适配 class → className style → 自动适配 React.CSSProperties

  4. defineProps + useAttrs 会自动合并类型 不用手动改。

  5. JS 项目直接用 会被编译成 const attrs = props,完全兼容。


五、总结

VuReact 处理透传 Attributes 的核心思想只有一句话: 把 Vue 隐式的 $attrs 变成显式的 useAttrs,再映射到 React 的 props 体系。

  • 你只管按 Vue 官方写法写
  • 编译器自动转成标准 React TSX
  • 类型安全、生产可用、迁移成本极低

正在做 Vue3 → React 迁移的同学,这套透传方案可以直接进团队规范。


🔗 相关资源


推荐阅读

#Vue3 #React #Vue转React #VuReact #前端迁移 #useAttrs #组件封装 #TypeScript

相关推荐
FungLeo1 小时前
成为全栈·Vue 管理后台篇·Vue Router如何守住多角色后台边界
前端·javascript·vue.js·rbac·vue router·路由守卫·前端权限
FungLeo1 小时前
成为全栈·Vue 管理后台篇·分页只显示第一页:从接口total 定位到前端修复
前端·vue.js·状态模式·分页·naive ui·服务端分页·前端问题排查
FungLeo2 小时前
成为全栈·Vue管理后台篇·仪表盘不是几张卡片:组合统计接口与角色视图
前端·javascript·vue.js·rbac·仪表盘·管理后台·tanstack query
ruanno_top2 小时前
可搜索的下拉框,键盘按不动:焦点进了下拉,事件还挂在触发器上
vue.js
FungLeo3 小时前
成为全栈·Vue 管理后台篇·Vue Query:服务端数据缓存、query key与变更失效
vue.js·数据获取·前端缓存·前端状态管理·tanstack query·vue query
北城笑笑3 小时前
Vue 109 ,从零搭建 Vue3 + Electron 工程:生态、安全桥接与打包选型( Vue + Electron )
前端·javascript·vue.js·安全·electron·vue
计算机毕设定制辅导-无忧学长5 小时前
《基于Spring Boot的迷游哈游戏综合服务平台的开发》
java·vue.js·spring boot·mysql·迷游哈游戏综合服务平台
非优秀程序员14 小时前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构
Highcharts.js19 小时前
Highcharts Orbit 完全指南:把每一张图表变成交互式分析工具
react.js·前端框架·highcharts·orbit·使用指南·ai 图表·交互式分析工具
tryCbest21 小时前
Vue系列——第 15 篇:内置组件全家桶——Transition、Teleport、Suspense、KeepAlive
前端·vue.js