useAttrs 和 useSlots 是 Vue 3 中获取透传属性与插槽内容的标准方式:useAttrs 返回未声明的 attribute 和事件监听器对象,useSlots 返回按名称索引的插槽函数,二者配合可实现 ref/事件透传等高级封装。

在 Vue 3 的 `<script setup>` 中,<strong>useAttrs 和 <strong>useSlots 是获取透传属性与插槽内容的标准方式,它们替代了旧版 setup 函数中通过 context 参数访问 `attrs` 和 `slots` 的写法。</script>
useAttrs:获取未声明的透传属性
它返回一个普通对象,包含所有未被 props 消费的 attribute(如 class、style、id、自定义属性)和事件监听器(如 @click、@input):
- 直接解构使用:
const { class: cls, style, ...rest } = attrs,适合做属性过滤或合并 - 常用于根元素继承:
<div v-bind="attrs"></div>,让父组件传入的 class/style 自动生效 - 若组件已声明
size: String,则attrs.size就不会存在——只有“未被 props 消费”的才进 attrs - 多根节点组件必须显式绑定:
<slot v-bind="attrs"></slot>,否则会报运行时警告
useSlots:获取插槽函数而非真实 DOM
它返回一个插槽对象,每个键(如 default、header)对应一个函数,调用后才得到 VNode 数组:
- 检查插槽是否存在:
!!slots.default或slots.footer !== undefined - 不直接操作 DOM —— 返回的是虚拟节点,需在模板中用
<slot name="header"></slot>渲染 - 作用域插槽照常使用:
<slot name="item" :item="item"></slot>,父组件用v-slot:item="{ item }"解构 - 逻辑处理时可调用:
slots.header?.()得到 VNode 列表,用于计算、遍历或条件判断
两者配合实现高级封装
单独用 useSlots 无法给插槽内容加 ref 或事件,但结合 useAttrs 可以透传这些能力:
立即学习“前端免费学习笔记(深入)”;
- 子组件模板中写:
<slot v-bind="attrs"></slot> - 父组件传入:
<MyComp ref="targetRef" @click="handleClick"><button>点我</button></MyComp> - 此时
targetRef就指向 button 渲染后的实际 DOM 元素,@click也正常触发 - 这种模式常见于按钮包装器、表单控件等需要透传 ref/事件的高阶组件
注意事项与常见误区
这两个函数不是响应式 API,返回值是普通对象/函数,不要试图用 watch 监听它们本身:
- 想响应插槽变化?应监听插槽内容中的响应式数据,或用
onUpdated捕获渲染时机 - 想过滤掉
ref或key?用解构排除:const { ref, key, ...restAttrs } = attrs - TypeScript 用户建议搭配
defineSlots声明插槽类型,提升类型安全 - 它们仅在 `<script setup>` 中需要;普通 setup 函数仍可通过 context.attrs/context.slots 获取</script>


















