vue3模板中ref的实现原理

总的来说:
ref 通过对象包装{ value })和 getter/setter 拦截 ,在模板编译阶段自动解包 .value,并利用响应式系统(track/trigger)实现依赖收集和更新触发,从而让基本类型和对象都能响应式变化。
精简版:

👉 ref 用对象存值,.value 触发响应式,模板自动解包。


Vue 3 模板中 ref 的实现原理详解

在 Vue 3 中,ref 是一个非常重要的响应式 API,用于创建可变的响应式数据 。它在模板组合式 API(Composition API) 中广泛使用。

本文将深入探讨:

  1. ref 的基本用法
  2. ref 在模板中的工作原理
  3. ref 的底层实现机制
  4. reactive 的区别
  5. 示例代码演示

📌 1. ref 的基本用法

ref 用于创建一个响应式引用 ,可以包装基本类型(如 numberstring)或对象:

javascript 复制代码
import { ref } from 'vue';

const count = ref(0); // 创建一个响应式 ref,初始值为 0

console.log(count.value); // 访问值需要使用 .value
count.value++; // 修改值

模板 中,Vue 会自动解包 .value,所以可以直接使用:

vue 复制代码
<template>
  <button @click="count++">{{ count }}</button>
</template>

📌 注意:

  • JS 中 访问 ref 必须用 .value
  • 模板无需 .value(Vue 自动解包)。

📌 2. ref 在模板中的工作原理

(1)为什么模板里不用 .value

Vue 的模板编译器 在编译阶段会对 ref 进行特殊处理:

js 复制代码
<template>
  <div>{{ count }}</div>
</template>

会被编译成:

javascript 复制代码
import { ref } from 'vue';

setup() {
  const count = ref(0);
  return { count }; // 返回 ref 对象
}

Vue 在渲染时 自动调用 .value

javascript 复制代码
// 伪代码:Vue 内部处理
render() {
  return h('div', count.value); // 自动解包
}

(2)ref 在模板中的响应式更新

ref.value 变化时,Vue 的响应式系统会触发组件更新:

javascript 复制代码
count.value = 10; // 修改 ref,触发重新渲染

底层机制

  1. ref 内部使用 ReactiveEffect 进行依赖收集。
  2. 模板中使用 ref 时,Vue 会自动追踪依赖
  3. ref.value 变化时,触发 组件的重新渲染

📌 3. ref 的底层实现原理

(1)ref 的核心实现

ref 的源码(简化版):

javascript 复制代码
function ref(value) {
  return {
    _isRef: true, // 标识是 ref 对象
    _value: value, // 存储值
    get value() {
      track(this, 'value'); // 依赖收集
      return this._value;
    },
    set value(newVal) {
      if (newVal !== this._value) {
        this._value = newVal;
        trigger(this, 'value'); // 触发更新
      }
    }
  };
}

📌 关键点:

  • ref 返回一个对象 ,包含 value 的 getter/setter。
  • track() :在 get 时收集依赖(模板、计算属性等)。
  • trigger() :在 set 时触发更新。

(2)ref vs reactive

特性 ref reactive
适用类型 基本类型 + 对象 仅对象/数组
访问方式 .value(JS 中) 直接访问属性
模板解包 自动解包(无需 .value 无需解包
实现方式 基于 getter/setter 基于 Proxy

为什么 ref 需要 .value

因为 ref 可以包装基本类型(如 number),而 JavaScript 的 Proxy 无法代理基本类型,所以必须用对象包装。


📌 4. 示例:ref 在模板中的使用

示例 1:计数器

js 复制代码
<template>
  <button @click="increment">{{ count }}</button>
</template>

<script setup>
import { ref } from 'vue';

const count = ref(0);

function increment() {
  count.value++; // 修改 ref
}
</script>

✅ 运行效果:

  • 点击按钮,count 自动更新并重新渲染。

示例 2:DOM 引用

js 复制代码
<template>
  <input ref="inputRef" />
  <button @click="focusInput">Focus Input</button>
</template>

<script setup>
import { ref } from 'vue';

const inputRef = ref(null); // 存储 DOM 引用

function focusInput() {
  inputRef.value.focus(); // 访问 DOM 元素
}
</script>

✅ 运行效果:

  • 点击按钮,input 自动聚焦。

📌 5. 总结

  1. ref 的作用:创建响应式数据(基本类型 + 对象)。
  2. 模板中的 ref
    • 自动解包 .value(无需手动写)。
    • 修改 ref.value 触发重新渲染。
  3. 底层原理
    • 基于 getter/setter + 依赖收集(track/trigger)。
    • reactive 更灵活(支持基本类型)。
  4. 适用场景
    • 基本类型的响应式数据(如 numberstring)。
    • 存储 DOM 引用(<div ref="el">)。
    • 需要明确 .value 访问的情况(更可控)。

🚀 进阶建议:

  • 如果想深入 Vue 响应式系统,可以研究 effecttracktrigger 的源码。
  • 在组合式 API 中,refreactive 可以结合使用。

希望这篇解析能帮助你彻底理解 ref 的工作原理!🎯

相关推荐
paopaokaka_luck9 分钟前
基于SpringBoot+Uniapp的健身饮食小程序(协同过滤算法、地图组件)
前端·javascript·vue.js·spring boot·后端·小程序·uni-app
患得患失94943 分钟前
【前端】【vscode】【.vscode/settings.json】为单个项目配置自动格式化和开发环境
前端·vscode·json
飛_1 小时前
解决VSCode无法加载Json架构问题
java·服务器·前端
YGY Webgis糕手之路3 小时前
OpenLayers 综合案例-轨迹回放
前端·经验分享·笔记·vue·web
90后的晨仔4 小时前
🚨XSS 攻击全解:什么是跨站脚本攻击?前端如何防御?
前端·vue.js
Ares-Wang4 小时前
JavaScript》》JS》 Var、Let、Const 大总结
开发语言·前端·javascript
90后的晨仔4 小时前
Vue 模板语法完全指南:从插值表达式到动态指令,彻底搞懂 Vue 模板语言
前端·vue.js
德育处主任4 小时前
p5.js 正方形square的基础用法
前端·数据可视化·canvas
烛阴4 小时前
Mix - Bilinear Interpolation
前端·webgl
90后的晨仔4 小时前
Vue 3 应用实例详解:从 createApp 到 mount,你真正掌握了吗?
前端·vue.js