Day 1 重学Vue:响应式系统的“底层逻辑”变更,Vue2旧时代的终结与Vue3新时代的开启

工作了将近10的前端,计划用30天的时间,系统整理vue知识点,DAY 1 的响应式开始。静下心来相信一定有所收获

下面是vue2 与 vue3 手写计数器

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Vue2 vs Vue3 计数器 · 响应式对比</title>
  </head>
  <!-- // 引入vue2和vue3的cdn -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  <body>
    <h1>vue 2 的 计数器</h1>
    <div id="app">
      <p>{{ count }}</p>
      <button @click="count++">增加</button>
      <button @click="count--">减少</button>
      <button @click="count = 0">重置</button>
    </div>
    <script>
      new Vue({
        el: '#app',
        data() { // 问题1:为什么是一个函数呢
          return {
            count: 0
          }
        }
      })
    </script>
    <h1>vue 3 的 计数器</h1>
    <div id="app2">
      <p>{{ count }}</p>
      <button @click="count++">增加</button>
      <button @click="count--">减少</button>
      <button @click="count = 0">重置</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@3"></script>
    <script>
      const { createApp, ref } = Vue; // 问题2:这里是引用的是 ref 那么复杂类型呢
          setup() {
            const count = ref(0);
            return { count };
          }
      }).mount('#app2');
    </script>
      问题3 : vue2 和 vue3 一个是 option API 一个是compsistion API  ,核心的问题响应式为何修改呢
  </body>
</html>

上述代码很直观的反馈出来Vue2Vue2 的区别 下面将围绕以下三个问题进行刨析:

  • Vue2的data为什么必须是一个函数?
  • Vue3的refreactive有什么区别?各自适合什么场景?
  • 为什么Vue3要改用Proxy替代Vue2的Object.defineProperty

Vue2 Data 为什么是一个函数 及其 属性避坑


解析 vue2 实例种data 可以是个对象,但是组件中的就必须是函数

核心原因:数据隔离
  • 对象形式 :JavaScript 中的对象是引用类型。如果 data 是对象,所有组件实例将共享同一个内存地址。修改实例 A 的数据,实例 B 也会跟着变。

  • 函数形式 :当 data 是一个函数时,每次创建新实例,Vue 都会调用该函数,返回一个全新的数据对象拷贝。这保证了每个组件实例数据的独立性。

  • 总结: 原因很简单,就是对象如果key值一样会被覆盖,但是函数一直是唯一的

    扩展:

  1. vue2 的执行顺序:

    PropsMethodsDataComputedWatch

  2. vue2 的生命周期 :

    创建阶段挂载阶段更新阶段销毁阶段 beforeCreatedCreatedbeforeMountMountedbeforeUpdateupdatedbeforeDestroydestroyed

    其中这个 activateddeactivated 是当keep-alive 触发

为什么Vue3要改用Proxy替代Vue2的Object.defineProperty


在还没有出现Proxy 时候,JS 只能用 Object.definedProperty 来监听属性

弊端:

  1. ❌ 无法监听新增属性
  2. ❌ 无法监听数组下标
  3. ❌ 必须提前知道属性名,无法动态拦截所有操作
Proxy 出现

Proxy 是 ES6(2015)引入的一个强大特性,它的中文意思是"代理"。

你可以用它来为一个对象创建一个代理,所有对原对象的操作(读、写、删除、遍历等)都会先经过这个代理。

js 复制代码
const proxy = new Proxy(target, handler);
  • target 是代理的对象
  • handler 一个对象,定义拦截处理函数
  • 返回的代理对象,你应该使用它代替原对象 handler 中 函数
  1. get(target, key)
  2. set(target,key,vaue)
  3. has(target,key)
  4. deleteProperty(target,key)
  5. ownKeys(target)
  6. apply(target, thisArg, args)
  7. construct 使new

Vue3的refreactive有什么区别?各自适合什么场景?


  • Ref 的使用 作用: Ref 是一个普通的JavaScript 变量(可以是基本的数据类型,也可以是引用类型) 包装成的响应式的数据

官网文档的解释: 接受一个内布值,返回一个响应式的,可以更改的ref对象,此对象只有一个指向其内部的属性.value

参数

ref 的参数可以是: 基本数据类型、引用数据类型、DOM的ref属性值

基本用法

首先先看看ref 函数传入的参数为 原始数据类型的情况

原始数据类型有7个,分别:String/Bumber/Boolean/BigInt/Symbol/Null/Undefined

  • reactive 的 使用

作用:

与将内部值包装在特殊对象中的 ref 不同,reactive() 将使对象本身具有响应性

响应式对象是 JavaScript 代理,其行为就和普通对象一样。不同的是,Vue 能够拦截对响应式对象所有属性的访问和修改,以便进行依赖追踪和触发更新。

对比二者的区别 以及使用场景

优先用ref的场景

  • 基本类型数据(字符串、布尔值等)。
  • 需跨组件传递的独立值(props传递ref更安全)。
  • 需要整体替换的对象(如从API拉取全新配置)。

优先用reactive的场景

  • 关联属性组(如表单的{name, email, submitted})。
  • 深度嵌套对象(如user.orders[0].products)。
  • 无需替换根引用的对象(如组件局部状态)。

建议

  • 小项目用ref 减少心智负担
  • 中大型项目: 基础类型用 ref 关联对象用 reactive 混合的用 toRefs 解构造
相关推荐
cidy_982 小时前
Git Pull 代码冲突后完整回退教程
前端
张就是我1065922 小时前
一个 ZIP 文件,把 webshell 写到了不该在的地方
前端
张就是我1065922 小时前
SPIP 的一个漏洞:你以为过滤了,其实没过滤干净
前端
一tiao咸鱼2 小时前
我用 Claude 做了一个 AI 面试刷题系统,支持 DeepSeek / 阿里 / GPT 帮你打分
前端
掘金一周3 小时前
对车完全小白,不知买油买电还是买混动,求建议| 沸点周刊 7.2
前端·人工智能·后端
妙码生花3 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十六):目录结构更新、完善 token 系统(AI 表示 token 入库无需加密?)
前端·后端·ai编程
程序me3 小时前
Prompt、Context、Harness、Loop 之后是什么? AI工程下一个半年的关键词
前端·后端·ai编程
飞天狗4 小时前
线上Bug一直复现不了?我用Sentry把错误追踪效率提升了10倍
前端
Slice_cy4 小时前
对前端工程化的理解
前端