CodeWalk

Vue3 ref与reactive区别及实现原理

作者:编译有声 · 2026-05-30 12:55

说明Vue3中ref和reactive的区别、各自的使用场景,以及ref在模板中自动解包(unwrapping)的规则。它们底层是如何通过Proxy实现的?

回答

编译有声

ref vs reactive 核心区别

特性refreactive
数据类型任意值(基本类型+对象)仅对象(object/array/Map/Set)
访问方式.value属性直接访问
模板解包自动解包(顶层ref)不自动解包
响应式原理包装为RefImpl直接Proxy包装

ref实现原理

function ref(value) {
  return new RefImpl(value);
}

class RefImpl {
  constructor(value) {
    this.__v_isRef = true;
    this._value = toReactive(value); // 对象则转reactive
  }
  get value() {
    track(this, 'value'); // 收集依赖
    return this._value;
  }
  set value(newVal) {
    this._value = toReactive(newVal);
    trigger(this, 'value'); // 触发更新
  }
}

reactive实现原理

function reactive(target) {
  if (target && typeof target === 'object') {
    return new Proxy(target, handlers);
  }
  return target;
}

模板自动解包规则

<template>中,顶层ref自动解包(无需.value):

<script setup>
const count = ref(0);
const obj = reactive({ num: ref(10) });
</script>
<template>
  <p>{{ count }}</p>          <!-- ✅ 自动解包,显示0 -->
  <p>{{ obj.num }}</p>        <!-- ❌ 不解包,显示 RefImpl -->
  <p>{{ obj.num.value }}</p>  <!-- ✅ 需手动.value -->
</template>

ref声明对象时:ref(plainObject)内部自动调用reactive,所以arr.value[0]直接响应式。

使用建议:

  • 基本类型(string/number/boolean):必须用ref
  • 复杂对象(form、API响应):reactive更简洁
  • 需要重新赋值整个对象:ref更方便(obj.value = newObj vs reactive需要替换属性)
  • 跨组件传递/需解构:ref配合toRefs
  • 模板中使用:组合式设ref,纯数据对象设reactive