Vue知识总结

一、模板语法

  1. 模板语法: {{}}, computed ,watch
  2. 指令
  3. 条件渲染,列表渲染v-if v-for

二、组件

  1. 组件通信: 父子props,子父$emit,兄弟/跨层级 provide/inject, event bus,vuex/pinia
  2. 插槽:
  3. 生命周期

二、核心机制-响应式,双向绑定

核心思想是数据劫持+发布-订阅模式

2.1 原理

2.1.1 Vue 2的响应式原理:基于 Object.defineProperty

Vue 2通过 Object.defineProperty API来劫持数据的读取和设置(getter/setter)。

实现过程主要分为以下几个步骤:

  1. 数据劫持 (Observer)

    • 当一个普通的JavaScript对象被传入Vue实例作为 data 选项时,Vue会遍历此对象的所有属性。
    • 对于每个属性,Vue会使用 Object.defineProperty 重新定义它的 getset 方法。
    • 这样,当读取 (get) 这个属性时,Vue就知道"谁用了这个数据"。
    • 修改 (set) 这个属性时,Vue就能发出通知,告诉那些用到它的地方进行更新。
  2. 依赖收集 (Dep)

    • getter 中,Vue会进行依赖收集
    • 每个被劫持的属性都会拥有自己的一个依赖管理器 (Dep对象)
    • 当视图在渲染计算属性 在计算时,会创建一个Watcher (订阅者)。这个Watcher在求值过程中会触发数据的 getter
    • 此时,Dep 就会把这个当前的 Watcher 添加到自己的订阅者列表里。这就建立了"数据→依赖(Watcher)"的关系。
  3. 派发更新 (Notify)

    • 当数据的值被修改,即触发了 setter 时,Vue会通知对应的 Dep
    • Dep 会遍历它管理的所有 Watcher,并调用它们的 update 方法。
    • Watcherupdate 方法最终会触发组件的重新渲染(re-render)或计算属性的重新计算,从而将最新的数据反映到视图上。

Vue 2实现的局限性:

  • 无法检测对象属性的添加或删除 :由于 Object.defineProperty 是在初始化时遍历属性进行劫持的,所以后续新增的属性不是响应式的(需使用 Vue.set)。
  • 对数组的限制 :无法劫持数组的索引操作(如 arr[index] = newValue)和修改长度的操作(如 arr.length = 0)。Vue通过重写数组的7个变更方法(push, pop, shift, unshift, splice, sort, reverse)来实现数组的响应式。

2.1.2 Vue 3的响应式原理:基于 Proxy

Vue 3使用了ES6的 Proxy 来重写了响应式系统,解决了Vue 2的大部分局限性。

实现过程:

  1. 数据劫持 (Reactive)

    • Vue 3通过 reactive() 函数创建一个对象的响应式代理。
    • Proxy 可以拦截对一个对象任何性质 的操作,包括属性的读取 (get)、设置 (set)、删除 (deleteProperty)、in 操作符等共13种,而不仅仅是 getset
    • 这意味着,无论是已有属性还是新增、删除属性,都能被完美劫持。
  2. 依赖收集与派发更新 (Track/Trigger)

    • track (追踪) :在 Proxyget 拦截中,Vue会执行 track 函数,用于建立"目标对象→属性→依赖"的关系。这里的"依赖"在Vue 3中被称为 effect,类似于Vue 2的 Watcher
    • trigger (触发) :在 ProxysetdeleteProperty 等拦截中,Vue会执行 trigger 函数,它会根据操作的类型和key,找到所有相关的 effect 并执行它们。
  3. Ref

    • 对于原始值(如 number, string),Proxy 无法代理。Vue 3提供了 ref 函数来解决。
    • ref 会创建一个响应式的引用对象(RefImpl 实例),该对象的 .value 属性才是真正的值。访问 .value 时进行依赖收集,修改 .value 时触发更新

一个组件一个渲染 Watcher,不是多个,Dep是多个。 Watcher(订阅者)订阅了 Dep(发布者)。 你修改数据 -> 数据的 Dep (发布者) 发出通知 -> 所有订阅了该Dep的 Watcher (订阅者) 收到通知 -> Watcher 执行更新操作 -> 视图变化

kotlin 复制代码
// 伪代码,在 userInfo.age 的 getter 内部
if (Dep.target) { // Dep.target 就是当前正在执行的 Watcher (渲染 Watcher)
    dep.depend(); // 核心:让 Dep 收集这个 Watcher
}
return value;
scss 复制代码
// 伪代码,在 userInfo.age 的 setter 内部
set(newVal) {
  value = newVal;
  dep.notify(); // 核心:Dep 通知所有订阅者!
}

2.2 虚拟DOM

在 Vue 2 中,响应式系统和虚拟 DOM 是两个独立但协同工作的核心模块,两者共同支撑了 Vue 的数据驱动视图能力。

  • 响应式系统:负责追踪数据变化,当数据更新时通知相关依赖(组件)。
  • 虚拟 DOM:负责将数据变化高效地映射到真实 DOM,是响应式系统触发更新后的 "渲染执行者"。

2.3 模板编译

  • 阶段 1:解析(Parse)------ 模板 → AST
  • 阶段 2 转换(Transform)------ AST → 优化后的 AST
  1. 指令转换

    • v-if 转换为条件判断逻辑(if/else)。
    • v-for 转换为循环逻辑(Array.map)。
    • v-bindv-on 转换为对应的属性绑定和事件监听(如 onClick)。
    • {{ name }} 插值转换为 _ctx.name(访问组件上下文的变量)。
  • 阶段 3 生成(Generate)------ AST → 渲染函数

三、核心机制-组合式api

Vue 组合式 API 的原理是一个有机结合体:

  1. 以响应式系统为引擎refreactive 提供了数据驱动的动力。
  2. setup() 函数为入口和上下文:它创建了组件初始化的执行环境,并收集所有暴露出的状态和方法。
  3. 以生命周期钩子函数为连接器:它们将逻辑与组件的生命周期阶段挂钩。
  4. 以普通 JavaScript 函数为复用载体:通过函数和闭包,将响应式状态和逻辑封装成可复用的单元。

它并没有引入全新的魔法,而是更底层、更灵活地暴露了 Vue 响应式系统的能力,让开发者能够像编写普通 JavaScript 代码一样来组织组件逻辑,从而获得了更好的类型推断、逻辑复用和代码组织能力。

  • 当渲染函数读取到 setup 返回的某个响应式属性(如 count.value)时,就会触发该响应式属性的 getter,从而将这个组件的渲染 effect (可以看作是一个特殊的 Watcher)收集为依赖。这就建立了数据 → 视图的依赖关系。
  1. 虚拟Dom

四、高级特性 vue 2 mixin

Vue 中的 mixin 是一种代码复用机制,用于将多个组件中可复用的逻辑(如数据、方法、生命周期钩子等)提取到一个独立的对象中,然后在多个组件中 "混入" 这些逻辑,实现代码共享。

  1. 合并规则

    • 数据(data):组件自身数据优先级高于 mixin,若存在同名属性,组件数据会覆盖 mixin
    • 方法、计算属性:同名时,组件自身的会覆盖 mixin 的。
    • 生命周期钩子:mixin 中的钩子会比组件自身的同名钩子先执行(如 mixincreated 先于组件的 created 执行)。
    • 组件选项(如 componentsdirectives):会合并为一个对象,同名键会被组件自身覆盖。
  • 缺点

    1. 命名冲突风险:mixin 与组件、mixin 之间可能出现同名属性 / 方法,不易排查。

    2. 逻辑来源模糊:组件中使用的属性或方法可能来自多个 mixin,调试时难以追溯。

    3. 灵活性有限:无法向 mixin 传递参数,难以实现个性化逻辑。

    Vue 3 中推荐使用 组合式 API(setup 函数 + 自定义 Hooks) 替代 mixin,通过函数调用的方式复用逻辑,解决了 mixin 的命名冲突和来源模糊问题,更适合复杂场景。

五、keep alive

  1. 缓存机制
    <keep-alive> 会将包裹的组件实例缓存到一个内部对象(通常称为 cache)中,键值一般是组件的 name 或标签名。当组件需要被切换(如使用 <router-view>v-if)时,不会执行 beforeDestroydestroyed 生命周期,而是被缓存起来。

  2. 激活与失活

    • 被缓存的组件再次渲染时,不会执行 createdmounted 等初始化生命周期,而是触发 activated 钩子。
    • 组件被缓存隐藏时,不会销毁,而是触发 deactivated 钩子。
  3. DOM处理
    <keep-alive> 自身不会渲染 DOM 节点,也不会出现在组件的父链中。它会将缓存的组件实例保存在内存中,对应的 DOM 节点会被暂时移除或隐藏,重新激活时再插入到文档中。

    • activated 是 Vue 的特殊生命周期钩子 ,需要与 <keep-alive> 配合使用

为什么不会重新渲染?

Vue 的组件生命周期在首次加载 Tab2 时会正常执行:created -> mounted -> ...。

当你切换到 Tab1 时,Tab2 会执行 deactivated

当你再次切换回 Tab2 时,Vue 会直接从缓存中恢复它的整个实例(包括所有的数据、DOM状态),因此只会触发 activated 钩子,而不会再次触发 createdmounted

六、路由管理

vue-router

七、状态管理Pinia/Vuex

组件 -> Dispatch Action -> Commit Mutation -> Modify State 组件 -> Call Action -> Directly Modify State组件 -> Directly Modify State

其他、React Vue对比

react vue 有哪些功能是对方没有的?

  1. React 并发渲染 可中断 useTransition
  2. vue 双向绑定、类html模板语法指令系统
相关推荐
北海几经夏12 分钟前
React自定义Hook
前端·react.js
龙在天17 分钟前
从代码到屏幕,浏览器渲染网页做了什么❓
前端
TimelessHaze18 分钟前
【performance面试考点】让面试官眼前一亮的performance性能优化
前端·性能优化·trae
yes or ok30 分钟前
前端工程师面试题-vue
前端·javascript·vue.js
我要成为前端高手1 小时前
给不支持摇树的三方库(phaser) tree-shake?
前端·javascript
Noxi_lumors1 小时前
VITE BALABALA require balabla not supported
前端·vite
周胜21 小时前
node-sass
前端
aloha_1 小时前
Windows 系统中,杀死占用某个端口(如 8080)的进程
前端
牧野星辰1 小时前
让el-table长个小脑袋,记住我的滚动位置
前端·javascript·element
code_YuJun1 小时前
React 常见问题
前端