惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
腾讯CDC
D
Docker
G
Google Developers Blog
D
DataBreaches.Net
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
S
SegmentFault 最新的问题
The Cloudflare Blog
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
量子位
美团技术团队
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 饭特稠

10 年前端经验喂了狗 浪浪山老前端的2025 实时互动教育版的自定义 UI 如何开发 2024,在路上 当蓝牙键盘连不上电脑:一次意外的debug之旅 前端技术选型时有用的网站 好用的zsh插件,打造好用的命令行 2023年终总结:怀孕,装修,还贷和其他 分享一个URL正则 使用 scriptable 实现每日诗词小组件 如何使webpack编译 node_modules 中的 npm 包 小程序中实现图片旋转后保存 Custom Elements 和 Shadow DOM了解一下? CSS 原生嵌套来了 聊聊CSS 缓动函数的新成员linear() chatgpt: 在ts中如何声明一个全局类型 Workbox -- 为serviceWorker量身定做的工具 cache API简介 重新学车 魔幻2022
useAttrs 是响应式的吗(by 豆包)
饭特稠 · 2025-10-17 · via 博客园 - 饭特稠

在 Vue 3 中,useAttrs() 是响应式的。

当你使用 useAttrs() 时,它会返回一个包含组件接收的所有非 props 属性的对象,并且这个对象是响应式的。这意味着:

  1. 当父组件传递的属性发生变化时,useAttrs() 返回的对象会自动更新
  2. 你可以在模板或 watch 中监听这些属性的变化

示例:

import { useAttrs, watch } from 'vue'

export default {
  setup() {
    const attrs = useAttrs()
    
    // 监听 attrs 的变化
    watch(attrs, (newAttrs, oldAttrs) => {
      console.log('属性变化了', newAttrs, oldAttrs)
    }, { deep: true }) // 深度监听,因为 attrs 是对象
    
    return {
      attrs
    }
  }
}

需要注意的是,useAttrs() 返回的对象是一个 Proxy 对象,它本身是响应式的,但你不应该解构它,因为解构会失去响应性。如果需要使用某个特定属性,应该直接通过 attrs.propName 的方式访问。

attrs 是 ref 还是 shadowref

在 Vue 3 中,useAttrs() 返回的对象既不是 ref 也不是 shallowRef,而是一个响应式的 Proxy 对象,其特性更接近 reactive 创建的响应式对象,但有一些特殊处理。

具体来说:

  1. 不是 refref 用于包装基本类型或对象,访问时需要通过 .value 属性。而 useAttrs() 返回的对象可以直接访问属性(如 attrs.class),无需 .value

  2. 不是 shallowRefshallowRef 只对顶层值响应,而 useAttrs() 返回的对象对深层属性变化也是响应式的(如父组件传递的 obj 属性内部字段变化时,子组件能感知到)。

  3. 特性类似 reactive

    • 直接通过属性访问(attrs.xxx
    • 响应式更新(属性变化时触发组件更新)
    • 不能直接解构(解构会丢失响应性)

但它又不同于普通 reactive 对象:

  • 它是只读的(修改它不会影响父组件传递的属性)
  • 会自动排除已声明为 props 的属性
  • 包含 HTML 特性(如 classstyle)和事件监听器

示例验证:

import { useAttrs, isRef, isShallowRef, isReactive } from 'vue'

setup() {
  const attrs = useAttrs()
  console.log(isRef(attrs)) // false
  console.log(isShallowRef(attrs)) // false
  console.log(isReactive(attrs)) // true(在 Vue 内部实现中基于 reactive)
}

因此,useAttrs() 返回的是一个特殊的响应式对象,行为上更接近 reactive 创建的对象,但专为处理组件属性设计。

ref 和 reactive 的区别是什么

在 Vue 3 中,refreactive 都是用于创建响应式数据的 API,但它们的使用场景和特性有显著区别:

1. 处理的数据类型不同

  • ref:主要用于包装基本数据类型(String、Number、Boolean、Null、Undefined、Symbol),也可以包装对象或数组。

    const count = ref(0) // 基本类型
    const user = ref({ name: 'Alice' }) // 对象
    
  • reactive:只能用于包装对象或数组(引用类型),不能直接包装基本类型。

    const user = reactive({ name: 'Alice', age: 20 }) // 对象
    const list = reactive([1, 2, 3]) // 数组
    

2. 访问方式不同

  • ref:通过 .value 访问或修改其内部值(在模板中使用时会自动解包,无需 .value)。

    const count = ref(0)
    console.log(count.value) // 0
    count.value++ // 修改值
    
    // 模板中直接使用
    // <div>{{ count }}</div>
    
  • reactive:直接通过属性访问或修改,无需 .value

    const user = reactive({ name: 'Alice' })
    console.log(user.name) // Alice
    user.name = 'Bob' // 修改值
    

3. 响应式原理不同

  • ref:通过包装对象实现响应式(创建一个包含 .value 属性的 Proxy),对于基本类型是直接监听 .value 的变化,对于对象/数组则会内部调用 reactive 处理。

  • reactive:通过Proxy 代理对象实现响应式,直接监听对象的属性变化(包括新增、删除属性等)。

4. 解构/展开行为不同

  • ref:解构时如果是基本类型,会丢失响应性;如果是对象类型,解构后仍保持响应性(因为内部是 reactive 代理)。

    const count = ref(0)
    const { value: c } = count // 解构后 c 是非响应式的
    
  • reactive:直接解构会丢失响应性(因为解构后得到的是普通值),需要用 toRefs 转换后再解构。

    const user = reactive({ name: 'Alice', age: 20 })
    const { name, age } = user // 非响应式
    

    正确做法:

    import { toRefs } from 'vue'
    const { name, age } = toRefs(user) // 保持响应性
    

5. 适用场景

  • 优先用 ref 的场景:

    • 基本数据类型(如数字、字符串)
    • 需要独立使用的响应式值(如计数器、开关状态)
    • 组合式函数中返回响应式数据(方便统一处理)
  • 优先用 reactive 的场景:

    • 复杂对象或数组(如用户信息、列表数据)
    • 多个相关属性需要组合管理的情况(如表单数据)

总结

特性 ref reactive
数据类型 基本类型 + 对象/数组 仅对象/数组
访问方式 需要 .value(模板中除外) 直接访问属性
解构行为 基本类型解构会失活 直接解构会失活(需 toRefs
内部实现 包装对象 + 内部 reactive Proxy 直接代理对象

实际开发中,ref 因适用范围更广(可处理所有类型),且在组合式 API 中更易维护,使用频率通常高于 reactive