vue3中ref的作用及ref和reactive之间的转化

本文详细介绍了Vue3中ref的作用,包括在DOM节点和组件上的应用,以及ref状态用法与reactive的区别。通过示例展示了ref如何用于获取和修改状态,并解释了ref能直接拦截字符串而reactive不行的原因。此外,还探讨了ref和reactive之间的转化,通过toRefs函数将reactive对象的属性转化为ref,以便在不同场景下灵活运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ref的作用:

(1)第一个作用:和vue一样:

  • 绑在dom节点上拿到的是dom节点;
  • 绑在组件上拿到的是组件对象;

定义方式:

<template>
    <div>
        <input type="text" ref="mytextref">
        <button @click="handleClick()">change</button>
    </div>
</template>

<script>
import { ref } from '@vue/reactivity'
export default {
    setup(){
        const handleClick=()=>{
            console.log(mytextref.value)//必须“.value”才能拿到input标签
        }

        // 创建ref对象
        const mytextref =ref()
        return {
            handleClick,
            mytextref
        }
    }
}
</script>

重点强调:

<input type="text" ref="mytextref">
import { ref } from '@vue/reactivity' //导入ref
// 创建ref对象
const mytextref =ref()
//返回mytextref
return {
    mytextref
        }
console.log(mytextref.value)//必须“.value”才能拿到input标签

结果:一点击button按钮,就拿到了input节点:

(2) ref状态用法

<template>
    <div>
        <!-- 这里其实是{{myname.value}},不过直接写myname,它也给你当成myname.value -->
        {{myname}}
        <button @click="handleClick()">change</button>
    </div>
</template>
<script>
import { ref } from '@vue/reactivity'
export default {
    setup(){
        const myname = ref("yiyi")//拦截的是ref对象里的value属性
        const handleClick=()=>{
            console.log(myname) //=>ref对象
            console.log(myname.value)//=>yiyi
            myname.value = 'linlin'
        }
        return{
            myname,
            handleClick
        }
    }
}
</script>

结果:点击按钮myname.value的值被改变

重点代码:

const myname = ref("yiyi")//拦截的是ref对象里的value属性
const handleClick=()=>{
      console.log(myname) //=>ref对象
      console.log(myname.value)//=>yiyi
      myname.value = 'linlin'
}

ref状态用法和reactive定义状态的区别:

相比较reactive定义状态,使用的时候需要obj.myname,ref状态用法就很好,把myname定义成ref对象,直接用myname就可以了,或者是myname.value;

{{obj.myname}}

const obj=reactive({
            myname:"yiyi",
            myage:100
        })

  • 有区别的原理是因为:

ref能直接拦截到字符串,拦截到字符串的原理其实是拦截的是ref对象里的value属性;

const myname = ref("yiyi")//拦截的是ref对象里的value属性

但是 reactive 就不能拦截到字符串,只能拦截到对象和数组:

const obj=reactive({})//拦截对象,可行
const obj2=reactive([])//拦截数组,可行
const obj3=reactive("yiyi")//拦截字符串,不可行

所以ref状态用法在dom节点上,比reactive好用一写,所以常拿来定义状态时使用; 

ref和reactive之间的转化:

  • ref在dom上比reactive好用一点,但是在函数里的使用reactive又比ref要好用,所以各有各的优点;
  • 不过ref和reactive之间可以转化,这样就可以在dom中使用ref,在函数里面使用reactive,这样就可以使得各自的优势最大化;
  • 用toRefs(obj)进行转换:
<template>
    <div>
        //使用ref方式
        {{myname}}--{{myage}}
    </div>
</template>

<script>
//引入toRefs
import { reactive,toRefs } from '@vue/reactivity'
export default {
    setup(){
        //使用reactive方式
        const obj=reactive({
            myname:"yiyi",
            myage:100
        })
        return {
            //ref和reactive进行转换
            ...toRefs(obj),
        }
    }
}
</script>

toRefs(obj)是把一个reactive里面的每个属性转换成了ref对象,效果: 

console.log(toRefs(obj))

return里要对toRefs(obj)对象展开,因为return返回的也是一个对象; 

 

### Vue3 中 `ref` `reactive` 的响应式实现原理 #### 一、Vue3 响应式的整体机制 Vue3 使用了一种基于 Proxy 的全新响应式系统,取代了 Vue2 中的 Object.defineProperty 方法。Proxy 提供了一个更强大灵活的方式来拦截对象的操作行为[^1]。 当通过 `ref` 或 `reactive` 定义一个响应式变量时,Vue3 实际上会利用 JavaScript 的 Proxy 来追踪这些变量的变化,并在变化发生时通知视图更新。 --- #### 二、`ref` 的响应式实现原理 `ref` 是用来定义基本类型的响应式数据的一种方式。它内部实际上是一个包装器,将传入的值存储在一个带有 `.value` 属性的对象中。这样做的目的是为了使该值可以被检测到其变更。 以下是其实现的关键点: - 当调用 `ref(value)` 时,如果传递的是一个对象,则会自动将其换为 `reactive` 类型;如果是原始类型(如字符串、数字等),则保持不变。 - 在模板或其他地方访问 `ref` 数据时,Vue 自动解包 `.value`,使得开发者无需显式书写 `.value` 即可获取实际值[^3]。 代码示例展示如何使用 `ref` 并观察其工作流程: ```javascript import { ref } from &#39;vue&#39;; const count = ref(0); // 创建一个 ref 对象 console.log(count.value); // 输出初始值 0 count.value++; // 修改 .value 属性触发响应式更新 console.log(count.value); // 输出修改后的值 1 ``` --- #### 三、`reactive` 的响应式实现原理 `reactive` 主要用于处理复杂的嵌套对象结构。它的核心是通过 Proxy 拦截对对象属性的各种操作(读取、设置、删除等)。具体来说: - 调用 `reactive(obj)` 后返回的新对象是对原对象的一个代理版本。 - 如果尝试访问或更改此代理对象上的任何属性,都会触发相应的 getter setter 钩子函数。 - 这些钩子函数负责记录依赖关系以及后续的通知过程。 下面是一段简单的例子说明 `reactive` 的功能: ```javascript import { reactive } from &#39;vue&#39;; const state = reactive({ name: &#39;Alice&#39;, age: 25, }); state.age += 1; // 更改年龄属性触发响应式更新 console.log(state.name, state.age); // 打印 Alice 新的年龄值 ``` 需要注意的一点是,由于 `reactive` 返回的是一个新的代理实例,因此不能直接对其源对象进行赋值或者比较相等问题。 --- #### 四、两者的对比分析 尽管两者都服务于相同的最终目标——建立响应式链接,但在某些方面存在差异: - **适用范围**: - `ref`: 推荐用于简单基础类型的数据声明; - `reactive`: 更适合管理具有多层嵌套特性的复杂状态树。 - **性能开销**: - `ref` 添加额外一层封装 (`.value`) ,可能稍微增加内存消耗; - `reactive` 则直接作用于整个对象层次之上,通常效率更高一些。 总结而言,在选择工具之前应该考虑具体的业务需求个人偏好等因素再做决定。 --- ### 结论 无论是采用 `ref` 抑或是 `reactive` 方式来构建应用中的动态交互逻辑,背后均依托着强大的 Proxy 技术支持完成高效的双向绑定效果。理解清楚各自的特性有助于我们写出更加优雅简洁且易于维护的应用程序代码[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌依依

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值