源本科技 | 码上会

Vue3 基础与原理

2026/04/05
0
0

Vue3的响应式原理是什么

Vue3 的响应式核心是用Proxy 代理对象,替代了 Vue2 的 Object.defineProperty。它会把 data 里的对象 / 数组包一层代理,拦截对象的读取、修改、新增、删除等操作。当组件渲染时,会通过 track 收集用到这个数据的依赖(也就是组件渲染函数);一旦数据被修改,就通过 trigger 通知所有依赖更新,触发组件重新渲染。Proxy 优势很大,能监听数组下标、长度变化,还能监听对象新增 / 删除属性,配合 Reflect 操作对象,响应式更完整、性能也更好,从底层解决了 Vue2 响应式的很多缺陷。

Vue3的虚拟DOM是如何工作的

虚拟 DOM 就是用 JS 对象模拟真实 DOM 节点,叫 VNode。Vue 先通过渲染函数把模板编译成 VNode 树,而不是直接生成真实 DOM。当数据变化时,会生成新的 VNode 树,通过diff 算法和旧 VNode 树做对比,只找出变化的节点,再精准更新到真实 DOM 上,不用全量重绘。这样能大幅减少 DOM 操作,因为真实 DOM 渲染开销极大,虚拟 DOM 只做最小化的 DOM 更新,既提升渲染性能,又让跨平台渲染更方便,比如小程序、桌面端都能适配。

Vue3组件的生命周期钩子函数有哪些,它们各自的作用是什么

Vue3 组合式 API 里用 on 开头的钩子,setup 是入口,替代了 beforeCreate 和 created。onBeforeMount 是挂载前,DOM 还没生成;onMounted 挂载完成,DOM 已渲染,适合发请求、操作 DOM。onBeforeUpdate 数据更新、DOM 重新渲染前触发;onUpdated 是 DOM 更新后。onBeforeUnmount 卸载前,适合清除定时器、事件监听;onUnmounted 卸载完成。还有缓存组件用的 onActivated、onDeactivated,捕获子组件错误的 onErrorCaptured,这些钩子按阶段执行,帮我们控制组件从创建到销毁的全过程。

Vue3组件中data为什么是一个函数

因为组件会被多次复用,如果 data 是对象,所有组件实例会共用同一个引用地址,一个实例改数据,其他实例都会跟着变,出现数据污染。而 data 写成函数,每次创建组件实例时,都会调用函数返回一个全新的独立对象,每个实例都有自己的数据副本,互不干扰。这是 JS 引用类型的特性决定的,函数能保证每次都返回新对象,彻底避免多实例数据共享问题,是组件复用的基础保障。

Vue3中key属性的作用是什么

key 是给 diff 算法用的唯一标识,帮 Vue 精准识别每个节点。列表渲染时,不加 key,Vue 会尽量复用节点,容易出现节点错乱、数据对应错误。加了唯一 key,diff 对比时能精准匹配新旧节点,不胡乱复用,只更新需要变的内容,大大提升更新效率。key 必须唯一且稳定,不能用随机数或索引(数组变化会导致 key 失效),一般用后端返回的 id。简单说,key 就是给节点办“身份证”,让 Vue 更新时不认错、不瞎改。

Vue3中的指令和组件有什么区别

指令和组件定位完全不同。指令是对DOM 的底层操作封装,专注处理 DOM 行为,比如 v-if 控制显示、v-model 绑定数据、v-for 循环,是轻量的 DOM 增强工具,没有独立模板和逻辑,只作用于元素。组件独立的功能模块,有自己的模板、data、方法、样式,是完整的业务单元,可复用、可嵌套、可通信。简单记:指令管“DOM 怎么动”,是小功能;组件管“业务模块”,是大单元,日常开发组件做页面结构,指令做 DOM 细节处理。

Vue3的单向数据流是什么意思,对组件设计有什么影响

单向数据流就是数据只能从父组件通过 props 流向子组件,子组件不能直接修改 props 里的数据,只能通过 emit 触发事件,让父组件自己改。这样数据流向单一、清晰,出问题能快速定位源头,不会出现子组件乱改父数据导致的混乱。对组件设计影响很大:组件要设计成纯展示 / 纯逻辑,职责单一;子组件只接收数据、抛出事件,父组件统一管理状态,组件间解耦,维护和复用都更简单,避免复杂的双向绑定带来的调试难题。

Vue3中的动态和静态属性有什么区别

静态属性是写死在模板里的固定值,比如 class="box"、type="text",编译后不会变,Vue 会做静态提升优化,直接渲染,不参与响应式更新。动态属性是用v-bind 绑定的,比如:class="className"、:style="styleObj",值跟着组件数据变化,会被加入响应式监听,数据一变属性就更新。静态属性无开销,动态属性有响应式开销。Vue3 编译时会把静态属性抽离,只处理动态属性,大幅提升编译和渲染性能,开发时能写死的就别用动态绑定。

Vue3中v-if和v-show的区别是什么

两者都是控制显示隐藏,但实现方式天差地别。v-if是“真正的销毁 / 重建”,条件为 false 时,元素直接从 DOM 树移除,不渲染,初始渲染开销小,但切换频繁会反复创建销毁,开销大。v-show是通过 CSS 的 display 控制,无论条件真假,元素始终渲染在 DOM 里,只是显示隐藏,初始渲染开销大,但切换极快。使用场景:很少切换用 v-if,频繁切换(比如 tab 切换)用 v-show,v-if 还能配合 template 使用,v-show 不支持 template。

Vue3中如何进行条件渲染

Vue3 条件渲染主要靠v-if、v-else-if、v-else组合使用,根据表达式的真假,决定是否渲染对应内容。可以直接用在元素上,也能配合 <template> 标签使用,不会生成额外 DOM 节点,适合批量控制多个元素。v-if 按顺序判断,满足一个就渲染对应模块,其他跳过。注意 v-if 和 v-for 不要同节点使用,优先级冲突且影响性能。条件复杂时,可把判断逻辑写在 computed 里,让模板更简洁,这是最常用、最直观的条件渲染方式。

Vue3中的computed、methods和watch侦听器的区别

computed 是计算属性,依赖数据变化才重新计算,自带缓存,多次调用只执行一次,适合模板里的复杂数据计算。methods 是普通方法,每次调用 / 渲染就执行,无缓存,适合事件触发、业务逻辑处理。watch 是侦听器,专门监听数据变化,数据一变就执行回调,支持异步操作,无缓存,适合监听数据后做异步请求、复杂逻辑处理。简单记:要缓存、算数据用 computed;点按钮、执行业务用 methods;监听数据、做异步用 watch。

Vue3中如何使用watchers响应数据变化

Vue3 组合式 API 里用 watch 和 watchEffect。watch 要明确指定侦听的数据源,比如侦听 ref、reactive 对象,接收新值和旧值,可配置 immediate(立即执行)、deep(深度侦听)。watchEffect 更智能,自动收集依赖,回调里用到的响应式数据变了就执行,不用手动指定数据源。一般简单侦听用 watch,需要自动追踪依赖用 watchEffect,侦听复杂对象时记得开 deep,或侦听对象具体属性,避免性能浪费。

Vue3中的nextTick是什么,它如何工作

nextTick 是等DOM 更新完成后再执行回调的 API。因为 Vue 更新 DOM 是异步的,数据修改后,不会立刻更新真实 DOM,而是先缓存更新,等同一轮事件循环结束再批量更新。这时直接获取 DOM 拿到的是旧数据,用 nextTick 就能拿到最新 DOM。比如修改数据后立刻获取 DOM 节点宽高、操作更新后的 DOM,就必须用 nextTick。它基于 Promise、MutationObserver 实现,保证回调在 DOM 渲染后执行,解决数据和 DOM 不同步的问题。

Vue3中如何使用过滤器,如何创建全局过滤器

Vue3彻底移除了过滤器,官方不再支持,推荐用 computed 计算属性或 methods 方法替代。如果非要实现全局过滤效果,可以把过滤方法挂载到 globalProperties 上,或者做成全局工具函数,在模板里直接调用。比如全局定义格式化方法,组件里直接使用。相比过滤器,computed 有缓存,性能更好,方法调用更直观,也更符合 Vue3 的设计理念,所以不用再纠结过滤器,直接用计算属性和方法就够了。

Vue3中的v-model是什么,如何自定义v-model

v-model 是双向绑定的语法糖,默认绑定 value 属性 + 监听 input 事件,数据变视图变、视图变数据变。Vue3 自定义 v-model 很简单,在子组件用 defineProps 接收自定义属性(比如 modelValue),再用 defineEmits 触发 update:modelValue 事件。父组件直接 v-model 绑定数据,子组件修改值时触发事件,就能实现自定义双向绑定。还能支持多个 v-model,给每个 model 指定名称,灵活适配表单组件、自定义输入组件等场景。