当前位置: 首页 > news >正文

【前端面试】Vue篇

响应式原理

Vue2 的 Object.defineProperty vs Vue3 的 Proxy

  • Vue2:按属性劫持,Object.defineProperty 给每个属性加 getter/setter,新增属性需 Vue.set,数组索引/length 不触发更新。
  • Vue3:按对象代理,Proxy 拦截整个对象,支持新增/删除属性、数组索引/length,性能更好。

为什么 Vue3 用 Proxy 替代 defineProperty

  • 解决了 Vue 2 中无法直接检测到对象属性的新增和删除 (Vue.set/Vue.delete) 的问题。
  • 解决了 Vue 2 中无法直接监听数组索引和 length 属性变化的问题。
  • 性能更好,Proxy 是惰性监听,只有当访问对象属性时才会进行代理操作。

Proxy 可以拦截哪些操作

  • get:拦截对象属性的读取。
  • set:拦截对象属性的设置。
  • has:拦截 propKey in proxy 的操作。
  • deleteProperty:拦截 delete proxy[propKey]
  • apply:拦截函数的调用。

refreactive 的区别与使用场景

  • reactive(obj):将对象变成响应式对象,深度代理。
  • ref(value):包装基本类型或对象为响应式引用,访问需 .value
  • 使用场景
    • 基本类型用 ref
    • 对象/数组用 reactive
    • 想解构对象响应式时也用 ref + toRefs

ref 可以大量替换成 reactive 吗?

不能完全替换。

refreactive 虽然都能实现响应式,但用途、结构、行为不同。有些场景可以互换,有些则不行。

如果如果是基本类型就不能用reactive,因为它只代理对象。

computed 和 watch 的区别

  • 依赖对象:computed 依赖数据计算结果,watch 监听具体数据。
  • 缓存机制:computed 有缓存,只有依赖变化才重新计算;watch 每次变化都触发回调。
  • 异步支持:computed 不适合异步操作,watch 可处理异步逻辑。
  • 返回值:computed 必须 return,watch 不需要。
  • 首次执行:computed 首次访问才计算,watch 默认不立即触发,除非 immediate: true
  • 适用场景:computed 适合复杂计算和模板渲染;watch 适合在数据变化时执行特定操作。

computed 和 watch 的依赖收集机制区别

  1. 触发方式不同
  • computed:基于“惰性求值 + 缓存”,只有当计算属性被访问时才触发依赖收集。
  • watch:立即执行回调或延迟执行,监听指定数据源,依赖收集发生在 watch 初始化时(或 getter 访问时)。
  1. 依赖收集对象不同
  • computed:收集计算属性内部访问的响应式数据作为依赖。
  • watch:收集 getter 或直接指定的响应式数据作为依赖。
  1. 执行时机不同
  • computed:依赖变化时标记为“脏”,下一次访问时重新计算。
  • watch:依赖变化立即触发回调。
  1. 用途差异
  • computed:用于“模板或逻辑中依赖的计算值”,缓存优化性能。
  • watch:用于“数据变化副作用”,如 API 调用、手动 DOM 操作等。

总结记忆法

  • computed = 惰性 + 缓存 + 依赖内部访问
  • watch = 监听变化 + 回调副作用

Computed 计算属性原理,怎么实现惰性求值

Computed 计算属性原理

  • computed 本质上是 带缓存的 getter 函数,依赖 Vue 的响应式系统。
  • 每个 computed 属性内部有一个 Watcher 实例,用来收集依赖。
  • 当依赖的响应式数据变化时,Watcher 会被标记为 dirty(脏)。
  • 下次访问 computed 时,如果 dirty 为 true,则重新计算并缓存结果,否则直接返回缓存值。

惰性求值

  • computed 只有在访问时才执行 getter,而不是依赖变化时立即计算。
  • 通过 dirty 标记 + 缓存值 实现惰性和高效更新。

watch 的原理

  • watch 本质是 侦听器(Watcher) ,依赖 Vue 的响应式系统。
  • 当被 watch 的响应式数据变化时,Watcher 会触发回调函数。
  • 可以支持异步操作,并且可通过 immediate: true 立即触发一次回调。
  • 内部流程
    1. 创建 Watcher 实例,收集依赖。
    2. 数据变化时触发依赖通知(Observer -> Dep -> Watcher)。
    3. 执行回调,更新业务逻辑或触发副作用。

Vue3 watch 和 watchEffect 的区别

  1. 依赖收集方式
  • watch:显式指定要监听的数据或 getter 函数。
  • watchEffect:自动收集运行时访问的所有响应式数据。
  1. 执行时机
  • watch:数据变化后触发回调,可选择立即触发 (immediate)。
  • watchEffect:创建时立即执行一次,并在依赖变化时重新执行。
  1. 适用场景
  • watch:适合监听特定数据变化,执行副作用逻辑。
  • watchEffect:适合依赖多个响应式变量的副作用,减少手动指定依赖。

为什么大量数据变化只更新一次

多次改值 → watcher 入队列去重 → nextTick 批量更新一次页面

  • Vue 在数据频繁变化时只会更新一次,是因为它 采用异步更新 + watcher 去重
  • 每次数据变化,相关 watcher 会被推入一个队列,但同一个 watcher 只会存在一次(通过 id 去重)。
  • 队列会在 下一个事件循环 执行,批量更新视图。
  • 这样,无论数据变化多少次,页面只会触发一次更新,提升性能。

Vue3 的 effect / tracker / trigger 概念

effect = 副作用函数,tracker = 收集依赖,trigger = 数据变化触发更新

  • 可结合 Vue3 Proxy 响应式实现:gettracker 收集依赖,settrigger 通知更新。
  • 可以和 Vue2 的 Object.defineProperty 对比:Vue2 getter 收集依赖,setter 触发更新。
  1. effect
  • 响应式副作用函数,当依赖的响应式数据变化时自动重新执行
  • 在 Vue 中,模板渲染函数和 computed 本质上都是 effect
  1. tracker
  • 又叫 依赖收集
  • effect 执行时,访问了哪些响应式数据,这些数据会记录 effect 为依赖。
  • 作用是 建立数据和 effect 的映射关系
  1. trigger
  • 数据变化时触发 effect
  • 当响应式数据被修改,trigger 找到依赖该数据的 effect 并重新执行。

生命周期

Vue2 生命周期

  1. 初始化阶段的钩子函数(初始化 Vue 实例)
  • beforeCreate():实例创建前,模板和数据均未获取到。
  • created():实例创建后,最早可以获得 data 数据,模板还没拿到。
  • beforeMount():数据挂载前,模板已经获取到,但数据未挂载。
  • mounted():数据挂载后,数据已挂载到模板中。
  1. 更新阶段的钩子函数(数据渲染,更新 Dom)
  • beforeUpdate():模板更新前,data 改变后,更新数据模板前调用。
  • updated():模板更新后,将 data 渲染到数据模板中。
  1. 销毁阶段的钩子函数(销毁实例)
  • beforeDestroy():实例销毁前。
  • destroyed():实例销毁后。

Vue2 父子组件生命周期执行顺序

  1. 挂载阶段
    父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted

  2. 更新阶段
    父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated

  3. 销毁阶段
    父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed

created 和 mounted 区别

  • created:组件实例创建完成,但 DOM 还未挂载
    • 常用于初始化数据、发起 API 请求或设置定时器。
  • mounted:组件的 DOM 已挂载到页面,可以访问真实 DOM 元素。
    • 常用于操作 DOM、第三方库初始化或需要依赖真实节点的逻辑。

组件中的 data 为什么是函数

避免多个组件实例共享同一 data 对象,造成数据冲突。

v-if 和 v-for 的优先级

  • Vue2v-for 优先级更高。
  • Vue3 中,v-if 的优先级更高。

keep-alive 缓存的具体内容

  • <keep-alive> 缓存的是组件实例,包括响应式状态和方法,而不仅仅是 DOM。
  • 缓存的组件不会重新执行 createdmounted,只触发 activated / deactivated
  • 可以通过 include/exclude/max 控制缓存策略。

keep-alive 缓存原理

Vue 内部维护一个缓存对象(key → 组件实例),渲染时优先复用缓存实例,超过 max 或不在 include 范围时清理旧实例。

组件销毁和内存泄漏问题

组件销毁 = 清理依赖、事件、子组件和引用;漏掉任何清理都可能造成内存泄漏。

  1. 组件销毁流程
  • Vue 组件有生命周期钩子,如 beforeDestroy / beforeUnmountdestroyed / unmounted
  • 销毁时会做以下操作:
    1. 移除组件自身的响应式依赖。
    2. 清理事件监听(包括 $on、DOM 事件)。
    3. 卸载子组件。
    4. 从父组件中移除引用。
  1. 内存泄漏的常见原因
  • 全局事件或定时器未清理(window.addEventListenersetInterval)。
  • 外部库引用未解除。
  • 对 DOM 或组件实例的引用未释放。
  1. 防止方法
  • beforeDestroy / beforeUnmount 中手动清理事件和定时器。
  • 避免在全局对象中持有组件引用。
  • 使用 Vue 提供的 $offclearInterval 等 API。

数据绑定

v-model 原理和用途

  • v-model 是 Vue 提供的 双向数据绑定语法糖,用于在 表单元素或组件中同步数据和视图。
  • Vue2:绑定 value + 监听 input 事件来实现双向绑定。
  • Vue3:支持自定义 prop 和事件,组件内部通过 emit('update:modelValue', newValue) 更新父组件状态,可以多个 v-model,对应不同 prop。
  • 用途
    • 表单输入同步:inputtextareaselect
    • 自定义组件状态双向绑定。
    • 减少手动写事件和 props 的样板代码。

Vue2 双向绑定原理

  1. 数据劫持:通过 Object.defineProperty 遍历 data 中所有属性,为每个属性添加 getter(收集依赖)和 setter(触发更新)。
  2. 模板解析:编译器扫描模板,将指令转换为渲染函数,同时为每个依赖数据的 DOM 节点创建 Watcher 实例。
  3. 依赖收集:首次渲染时,访问 data 属性触发 getter,将 Watcher 实例添加到该属性的 “依赖列表” 中。
  4. 响应式更新:数据变化触发 setter,遍历依赖列表,调用所有 Watcherupdate 方法,更新对应的 DOM 节点。

在这里插入图片描述

Vue2 中如何检测数组的变化?

在 Vue2 中,数组的变化 不能被直接劫持索引或 length,所以 Vue2 通过 重写数组的七个变异方法 来实现响应式。

  • 当调用这些方法修改数组时,Vue 会触发依赖更新,视图自动刷新。
  • 如果直接用索引修改,如 arr[0] = 1,则不会触发更新,需要用 Vue.set(arr, 0, 1)this.$set(arr, index, value) 来保证响应式。

this.$set 用法

给对象新增响应式属性,解决 Vue2 无法监听新增属性问题。

this.$nextTick 作用及原理

  • 作用在下次 DOM 更新循环结束之后执行回调,保证获取到的是最新的 DOM 状态。
  • 原理Vue 的 DOM 更新是异步的,$nextTick 把回调推迟到 “下次 DOM 更新循环结束后” 执行,确保能获取更新后的 DOM。

组件通信

父子组件通信

  • props 传值,事件 $emit 通知父。

子组件能否直接修改父组件的值

子组件不应该直接修改父组件的 props,因为 props 是父组件单向下传的数据,直接修改会破坏单向数据流,Vue 会在控制台提示警告。

平行组件通信

  • 借用父组件实现平行组件间通信。
  • 事件总线(小型项目)。
  • Vuex / Pinia(大型项目)。
  • provide/inject(跨层级)。

插槽(slot、具名插槽、作用域插槽)

  • 具名插槽:带有 name 属性,一个组件可以有多个具名插槽。
  • 匿名插槽:没有 name 属性,一个组件只能有一个匿名插槽。
  • 作用域插槽:是子组件提供数据、父组件自定义渲染的插槽。

provide / inject

provide 父组件提供,inject 子组件注入,跨层传递数据,减少 props 链式传递。

provide / inject 是 Vue 提供的 跨级组件通信机制

  1. provide
  • 在父组件或祖先组件中声明要提供的数据。
  • 通过对象或函数返回给后代组件使用。
  1. inject
  • 在子组件或后代组件中声明依赖的键。
  • 可以访问父组件或祖先组件提供的数据。

特点

  • 数据 单向传递,子组件修改不会影响父组件。
  • 适合跨多层组件传递数据,避免层层 props 传递。
  • 不是响应式的默认机制,如果需要响应式,需要在 provide 时用 reactiveref 包裹。

Composition API

为什么引入?

解决 Options API 中逻辑复用难、组件大型化后管理困难的问题。

Teleport / Suspense 简单使用场景

  • <Teleport> (传送门)

    • 作用:允许我们将一个组件的内容渲染到 DOM 树的另一个位置。
    • 典型场景:创建全局的模态框(Modal)、弹窗(Dialog)、通知(Notification)等。这些组件在逻辑上属于当前组件,但在视觉上需要脱离当前组件的 DOM 结构(例如挂载到 <body>下),以避免 z-indexoverflow 的问题。
  • <Suspense> (实验性)

    • 作用:用于优雅地处理异步组件或异步 setup 函数。
    • 如何工作:它提供了两个插槽 #default#fallback。当 default 插槽内的异步组件正在加载时,会显示 fallback 插槽的内容(如 Loading 动画)。加载完成后,再切换回 default 内容。这简化了自己写 v-if="loading" 的逻辑。

虚拟 DOM

原理、作用、解析过程

原理

  • Vue 模板被编译成渲染函数,返回虚拟 DOM(VNode)树。
  • 数据变化时,生成新的 VNode 树。
  • 对比新旧 VNode 树(Diff 算法),找出最小变更。
  • 将差异应用到真实 DOM(Patch),更新视图。

作用

  1. 性能优化:避免频繁操作真实 DOM,通过 diff 算法批量更新最小化真实 DOM 变更。
  2. 跨平台:在不同环境(Web、Weex、Native)都可以渲染,因为虚拟 DOM 只是 JS 对象。

解析过程

  1. 模板编译:Vue 模板 → 渲染函数 → 生成虚拟 DOM(VNode)。
  2. 渲染:渲染函数返回 VNode 树,描述当前视图状态。
  3. 更新(Diff):数据变化 → 新旧 VNode 树对比 → 找出最小变更。
  4. 打补丁(Patch):将差异应用到真实 DOM,更新视图。

diff 算法(Vue2 vs Vue3)

  • 静态标记:Vue2 全量遍历,Vue3 仅对比带 PatchFlags 的动态节点。
  • 数组 Diff:Vue2 双端对比(O(n)),Vue3 最长递增子序列(O(k),少 DOM 移动)。
  • 优化逻辑:Vue2 纯运行时 Diff,Vue3 编译预优化 + 运行时按需对比。

两者均对比新旧 VNode 更优更新 DOM,Vue3 针对 Vue2 全量 Diff 痛点,用静态标记 + LIS 算法优化,聚焦动态节点和最少 DOM 操作,复杂组件 / 长列表性能提升明显。

key 的作用

  1. 为了性能优化:Vue 底层是虚拟 Dom,更新时使用 diff 算法,为每个节点设置 key 值,方便 Vue 判断节点是否可以复用,从而提高渲染效率。
  2. 确保正确的组件状态:在使用带有状态的组件时,如果不使用 key,容易出现状态错乱的问题,使用 key 可以确保每个节点都能正确保存组件状态。

v-if vs v-show

  • v-show:元素始终渲染到 HTML 中,通过修改元素的 CSS 属性 display 来决定显示还是隐藏。
  • v-if:满足条件才会渲染到 HTML 中,通过操作 DOM 元素来切换显示。

路由

路由跳转方式

  1. 使用 <router-link> 标签。
  2. 使用 this.$router.push 方法。
  3. 使用 this.$router.replace 方法。
  4. 使用 this.$router.go 方法。

动态路由

  1. 动态路由
  • 在路由配置中可以使用 占位符(如 /index/:id)表示参数。
  • 路由跳转时传入参数,组件通过 $route 获取对应值。
  1. 传参方式
  • params 参数
    • 路由路径带占位符。
    • 参数通过 $route.params 获取。
    • 不显示在 URL 中,刷新后会丢失。
  • query 参数
    • 路由路径正常。
    • 参数通过 $route.query 获取。
    • 显示在 URL 中,刷新不会丢失。

路由守卫

  • 全局前置钩子beforeEach
  • 路由独享守卫beforeEnter
  • 组件内钩子beforeRouterEnterbeforeRouterUpdatebeforeRouterLeave

为什么 Vue 和 React 都选择自己实现路由?

核心需求:SPA 要求路由跳转时不刷新页面,仅更新页面内容(组件切换),而原生 <a> 标签跳转会刷新页面,无法满足需求。

  1. 保持框架风格一致
  • Vue、React 都是组件化框架,希望路由也能用组件的方式声明式使用
  • 自研路由可以无缝和响应式系统、生命周期机制整合。
  1. 统一生态标准
  • 官方路由能提供一致的 API、约定和最佳实践。
  • 避免社区出现多个实现方式导致学习成本高、兼容性混乱。
  1. 更好地集成框架特性
  • Vue Router 能和 Vue 的 响应式系统、keep-alive、transition 深度联动。
  • React Router 能利用 React hooks(如 useNavigate, useParams)与组件状态自然融合。
  1. 控制渲染流程与性能
  • 框架自己控制路由切换时的组件卸载、缓存、动画、懒加载等细节。
  • 能更好地做动态导入、SSR 支持(如 Next.js、Nuxt)。
  1. 生态闭环
  • 路由是前端 SPA 的核心,官方实现意味着框架能提供从渲染到导航的一体化方案,增强生态控制力与可维护性。

浏览器本身就有路由,为什么不直接用 a 标签跳转?

因为前端框架的“路由跳转”不是刷新整个页面,而是在单页应用(SPA)中切换视图、复用资源,提升性能与体验。

  • <a> 标签跳转 → 后端控制页面渲染
  • Router 跳转 → 前端控制视图切换

前端路由的本质是 “不刷新页面的页面切换” ,让 SPA 应用更快、更流畅。

history 导航时,页面真的切换了吗?怎么做到的?

history.pushState() 并没有真正让浏览器“切换页面”,而是“在同一个页面里切换视图 + 改地址”。这就是浏览器支持单页面路由的本质。

原生 JS 如何进行路由监听?

有两种方式:hash 模式 和 history 模式。

  • Hash 模式:监听 hashchange 事件。
  • History 模式:监听 popstate 事件。

没有 hash 的路由如何进行监听?

使用 HTML5 History APIpushState / replaceState + popstate

  • 浏览器的前进、后退操作会触发 popstate
  • 但主动调用 pushState() 不会触发,需要自己派发或封装监听。

onpopstate 可以监听到 pushstate 事件吗?

不能onpopstate 只在用户点击浏览器的前进/后退,或调用 history.back()history.forward()history.go() 时触发。主动调用 pushState()replaceState() 不会触发。框架通常会在调用后手动执行路由更新逻辑。


性能优化

Vue 性能优化策略

  1. 模板和渲染优化
  • 使用 v-if / v-show 区分频繁切换和固定显示的元素。
  • 对列表使用 key 提高虚拟 DOM 节点复用效率。
  • 静态内容标记为 静态节点,减少重复渲染。
  • 组件懒加载,按需加载路由或组件。
  1. 响应式数据优化
  • 避免不必要的响应式数据,减少 watcher 数量。
  • 对复杂对象使用 computed 缓存计算结果。
  • 对频繁变化的数据,使用 v-once / v-memo 避免重复渲染。
  1. 事件与 DOM 操作优化
  • 使用事件修饰符和 节流 / 防抖 减少频繁回调。
  • 频繁切换元素时,使用 v-show 替代 v-if
  1. 内存和资源优化
  • 组件销毁时清理事件监听、定时器、第三方库引用。
  • 使用 keep-alive 缓存组件状态,但注意释放不再使用的组件。
  1. 服务端渲染(SSR)与懒加载
  • 对首屏渲染优化,减少首次加载时间。
  • 异步组件和路由懒加载减少 JS 包体积。

设计模式

Vue 中使用的设计模式

  1. 观察者模式
    • 数据变化通知依赖更新,是 Vue 响应式系统的核心。
  2. 发布-订阅模式
    • Watcher 订阅数据变化,Observer 发布变化。
  3. 策略模式
    • 不同渲染模式、生命周期钩子处理、指令更新方式等采用策略模式封装。
  4. 工厂模式
    • 创建 VNode、组件实例、渲染函数等对象。
  5. 单例模式
    • VueRouter、Vuex 实例在应用中通常是单例。
  6. 代理模式
    • 用于数据代理和响应式实现,代替 Vue2 的 Object.defineProperty

MVVM 和 MVC 模式的区别

MVC(Model-View-Controller)是一种将应用拆分为模型、视图和控制器的架构模式:

  • Model:管理数据和业务逻辑。
  • View:负责 UI 展示。
  • Controller:处理用户输入,更新 Model 并通知 View。
  • 数据流通常是 用户操作 → Controller → Model → View,视图和数据绑定是手动的。

MVVM(Model-View-ViewModel)在 MVC 基础上演化,引入了 ViewModel 作为桥梁,实现 数据双向绑定

  • Model:管理数据。
  • View:展示 UI。
  • ViewModel:将 Model 数据映射到 View,并将用户操作同步回 Model。
  • 数据变化自动更新视图,视图操作也会自动更新数据。
  • Vue、Angular 是典型的 MVVM 框架。

核心区别

  • MVC 依赖 Controller 手动更新视图,MVVM 通过响应式双向绑定自动同步数据和视图。
  • MVC 数据流单向,MVVM 数据流双向。
  • MVVM 更适合现代前端框架开发,减少 DOM 操作,提高开发效率。

Vue SSR 原理

  1. 服务端渲染
  • 将 Vue 组件在服务端渲染成 HTML 字符串。
  • 客户端拿到完整 HTML 可以直接展示页面,提升首屏渲染速度和 SEO 友好性。
  1. 渲染流程
  • 服务端
    1. Vue 组件生成渲染函数。
    2. 渲染函数生成 虚拟 DOM
    3. 将虚拟 DOM 转为 HTML 字符串返回给客户端。
  • 客户端
    1. 接收 HTML,展示页面。
    2. Vue 客户端挂载,进行 hydration,将静态 DOM 转换为可交互的 Vue 应用。
  1. 优化点
  • 可以结合路由懒加载、数据预取(asyncData / fetch)提高性能。
  • 避免服务端渲染副作用操作,如直接操作 DOM。

Vue 模板编译原理

  1. 模板解析
  • 将模板字符串解析成 抽象语法树(AST) ,描述节点结构和指令信息。
  1. 优化阶段
  • 标记静态节点、静态根,减少后续渲染过程中不必要的更新。
  1. 代码生成
  • 将 AST 转换成 渲染函数(返回 VNode),供 Vue 在渲染阶段调用。
  • 执行渲染函数生成 HTML。

Vuex

Vuex 实现原理

Vuex = 响应式 state + mutation 管理修改 + action 异步处理 + getters 计算状态

Vuex 是 Vue 的 集中式状态管理库,核心原理是通过 响应式对象 + 单向数据流 + 事件订阅机制 实现状态管理:

核心组成

  1. State:存储共享状态,是响应式对象,组件通过 mapStatethis.$store.state 访问。
  2. Getter:类似 computed,依赖 state 计算衍生状态,自动缓存。
  3. Mutation:唯一修改 state 的方式,同步操作,保证状态可追踪。
  4. Action:处理异步逻辑,内部调用 mutation 修改 state
  5. Module:支持模块化管理 statemutationactiongetter

数据流

Component -> dispatch action -> commit mutation -> update state -> view 自动更新
  • State 是响应式的,组件依赖收集后,会在 state 改变时自动重新渲染。
  • Vuex 内部通过 Vue 的响应式系统实现状态响应。

mutations 能否异步

不能。Vuex 所有状态更新唯一途径都是 mutation,异步操作通过 Action 来提交 mutation 实现,方便跟踪每一个状态的变化。若 mutations 是异步的,就无法很好地追踪状态,给调试带来困难。

刷新页面数据丢失问题

  • 原因:Vuex 数据保存在运行内存中,页面刷新会重新加载 Vue 实例,Vuex 数据就会被清空。
  • 解决方法
    1. 可结合 localStorage / sessionStorage 持久化。
    2. 使用插件,如 vuex-persistedstate 等插件来使 Vuex 数据持久化到本地中。

Vuex vs localStorage 区别

1. Vuex

  • 响应式state 是响应式的,数据变化会自动更新组件视图。
  • 临时存储:页面刷新后 state 会丢失(除非配合持久化插件)。
  • 单向数据流 + 可追踪:通过 mutations 修改 state,方便调试和管理复杂状态。

2. localStorage

  • 非响应式:直接存储在浏览器,本身不会触发组件更新。
  • 持久化存储:页面刷新不会丢失,适合保存登录信息、用户偏好等。
  • 手动管理:需要手动读取/写入,并手动同步到组件状态。

Vuex 和 Pinia 的区别

对比项VuexPinia
语法风格强调 mutation + action 的固定流程直接在 actions里改状态,更简洁
TypeScript 支持较弱,需要手动类型定义内置类型推导,TS 友好
模块化模块需命名空间(namespace)管理Store 是独立的,不需要命名空间
数据定义stategettersmutationsactions分开写全部集中在 defineStore里,更直观
调试工具支持 Vue DevTools同样支持(且更清晰)
兼容性Vue2/3 都能用(Vuex4 支持 Vue3)主要为 Vue3 设计(可在 Vue2 用插件兼容)
学习成本较高较低,语法接近 Composition API

为什么项目优先采用 Vuex 而不是 Pinia?

新项目会更倾向 Pinia,老项目或保守团队会优先 Vuex。

  1. 历史项目兼容性
  • 大量项目是 Vue2 架构,Vuex 已深度集成。
  • 升级到 Pinia 需改写逻辑、迁移工具链,成本高。
  1. 团队和生态惯性
  • Vuex 存在多年,文档、教程、插件生态成熟。
  • 老项目、老团队成员更熟悉 Vuex 的使用模式。
  1. 规范与稳定性
  • Vuex 强制使用 mutation 改状态,结构清晰、便于调试与规范团队协作。
  • Pinia 更灵活,但也意味着约束更少,对团队自律要求更高。
  1. 第三方依赖兼容
  • 一些旧组件库、插件仍默认依赖 Vuex(例如某些权限、缓存中间件)。

什么是状态管理?作用是什么?

  • 状态管理:数据需要保存在应用中某个位置,这些数据管理称之为状态管理。
  • 作用:当使用 Vue 进行单页应用开发时,经常会在各个组件之间数据通信,比较简单情况下,可以用 propsemit 事件进行传递,数据逻辑过于复杂时,需要状态管理。

其他

$attrs / $listeners / 插槽透传

$attrs 透传属性,$listeners 透传事件,插槽透传内容

  • Vue3$listeners 被合并到 $attrs 中,通过 v-on="$attrs" 透传事件。
  1. $attrs
  • 包含 父组件传递给子组件,但子组件没有显式声明的 props
  • 常用于 将未声明的属性透传给子组件的根元素或子组件
  1. $listeners(Vue2 特有)
  • 包含 父组件传递给子组件的事件监听器
  • 可以通过 $listeners 将事件透传给子组件内部元素。
  1. 插槽透传
  • 子组件内部使用 <slot><slot name="xxx"> 将父组件传入的内容渲染出来。
  • 可以实现 父组件内容在子组件内部复用

Vue 与 React 的区别

  • 模板方式:Vue 使用模板 + 指令,React 使用 JSX(函数式写法)。
  • 响应式机制:Vue 内置响应式(Vue2 Object.defineProperty / Vue3 Proxy),React 通过 setState 或 Hook 管理状态。
  • 数据流:Vue 默认单向 + 双向绑定(v-model),React 默认单向流。
  • 组件通信:Vue 提供 props / events / provide-inject / Vuex,React 主要通过 propsContext
  • 学习成本:Vue 上手快,React 更偏向函数式和组合式思维。

Vue2 与 Vue3 的区别

  • 响应式实现:Vue2 用 Object.defineProperty,Vue3 用 Proxy,更高效、支持动态添加属性。
  • Composition API:Vue3 引入 Composition API,提高逻辑复用和组织能力。
  • 性能优化:Vue3 更小体积、更快虚拟 DOM,支持 tree-shaking。
  • Fragment / Teleport / Suspense:Vue3 支持多根节点组件、DOM 传送、异步组件占位渲染。

SPA 理解及优缺点

  • 理解:单页应用在首次加载后,通过 JS 控制页面路由,局部更新 DOM,而不是每次请求新页面。
  • 优点:体验流畅、减少页面刷新、前后端分离。
  • 缺点:首屏加载慢(需 SSR 优化)、SEO 较弱、浏览器历史管理需处理。

浏览器为什么支持单页面路由?

浏览器支持单页面路由,是因为提供了 Hash 和 History API,让前端可以修改 URL 而不刷新页面,从而实现 高性能、可导航、可回退的 SPA 体验。

v-html 原理

  • v-html 用于将字符串渲染为 HTML 内容
  • 本质是修改元素的 innerHTML
  • 安全风险:可能导致 XSS,需要确保内容可信。

组件中写 name 的好处

  • 调试工具中显示组件名称,更易定位问题。
  • 递归组件必须用 name 来引用自己。
  • keep-alive 中使用 include / exclude 缓存策略时依赖 name

index 做 key 的问题

在 Vue 中,key 用于标识列表中每个节点的唯一性,帮助虚拟 DOM diff 算法复用节点。

使用索引作为 key 的问题

  1. 当列表顺序发生变化(插入、删除、移动)时,索引会改变,虚拟 DOM 会认为节点是不同的,从而销毁重建,导致 性能浪费状态丢失(如 input 输入内容丢失)。
  2. 对于静态列表或不会变的列表,使用 index 可以,但对动态列表不推荐。

推荐做法

  • 尽量使用 唯一且稳定的 id 作为 key,以保证节点复用。

Vue 指令,如何添加自定义指令

Vue 指令

  • 指令是带有 v- 前缀的特殊属性,用来在 DOM 上执行特定操作,如 v-ifv-showv-model

自定义指令

  • Vue.directive 函数来添加自定义指令。
  • Vue 允许用户创建自定义指令,扩展 DOM 功能。
  • 核心是提供 生命周期钩子函数
    • bind / created:指令绑定到元素时执行。
    • inserted / mounted:元素插入 DOM 时执行。
    • update / updated:绑定值更新时执行。
    • unbind / unmounted:指令解绑时执行。

应用场景:如自动聚焦、拖拽、节流防抖等 DOM 操作。

http://www.dtcms.com/a/600800.html

相关文章:

  • AI重塑IT职场:挑战与机遇并存
  • 微信小程序uniapp开发附源码——长图拼接
  • MySQL【表的内外连接】
  • 名字姓名起名打分评分抖音快手微信小程序看广告流量主开源
  • Windows下使用 Docker 安装MySQL
  • 微信小程序里用 setData() 修改数据并打印输出 的几种写法
  • 微信小程序map组件聚合簇样式自定义
  • 河北住房和城乡建设厅网站电话海报设计图片简单
  • 好的俄文网站设计大学学风建设专题网站
  • 领域驱动设计系列文章汇总
  • C++11拓展语法
  • 智慧医疗:FHIR R5、联邦学习与MLOps三位一体的AI产品化实战指南(下)
  • 创建一个达梦库需要多大空间
  • Redis_11_类型补充+命令补充+RESP
  • 网站设计哪家便宜seo网站做推广公司
  • 用于感知图像超分辨率的自编码监督(易于理解版本)
  • 地图可视化实践录:空间分析库Turf.js的学习
  • 长沙制作网站公司哪家好广州seo推广营销
  • 11、prometheus-PromQL-5-聚合计算函数
  • (114页PPT)上海x友集团管理咨询及IT规划项目第一期报告管理诊断分析咨询报告(附下载方式)
  • C语言编译器 Visual Studio:实现高效编程与调试环境优化
  • 王树森深度强化学习 DRL(六)连续控制 DDPG + 随机策略
  • 【SatWetCH4 第一期】全球湿地甲烷排放通量估算过程模型 SatWetCH4 介绍
  • Opencv(十一) : 图像缩放
  • 开源 Objective-C IOS 应用开发(四)Xcode工程文件结构
  • 儿童网站 源码html5网站开发教学
  • 编译类语言的特点与应用
  • Python 数组使用方法总结
  • 网站风格变化免费logo在线制作头像
  • 第三章深度解析:智能体“大脑”的底层逻辑——大语言模型技术基石全拆解