VUE面试题
简述Vue3 computed 和 watch 的区别和运用的场景 ?
computed:
缓存机制:计算属性具有缓存机制,只有当计算属性的依赖发生变化时,计算属性才会重新计算。
自动取值与监听: 你只需要声明依赖了哪些数据,Vue会自动监听这些数据的变化。
不可直接修改:计算属性的值不能直接被修改,它们是只读的。如果需要修改计算属性的值,必须通过修改其依赖的数据来间接实现。
应用场景:
表单的校验结果,如根据输入值判断是否合法。
数据过滤和转换,比如将数组处理成特定格式的数据展示。
任何需要根据多个状态计算得出新值,并且这个值可能会被多次引用的情况。
watch:
命令式: 更为灵活,可以执行异步操作或者更复杂的逻辑处理。
手动触发: 需要手动指定监视的数据以及当这些数据变化时执行的函数。
一次性或持续性: 可以设置为立即执行一次(immediate: true)或者在数据变化时执行(默认)。
适合副作用:当数据变化需要触发某些操作作为副作用时,如发起网络请求、修改其他数据等。
应用场景:
当需要在数据变化时执行异步操作,如从服务器获取数据。
当需要在数据变化时执行复杂的业务逻辑,这些逻辑不适合放在计算属性或方法中。
当需要在数据变化时触发其他响应,例如路由跳转、状态更新等。
当需要在数据变化时进行深层次的对象或数组侦听,watch 属性可以配置 deep 选项来实现深度侦听。
区别:
性能考虑:对于纯粹的计算属性,computed由于其缓存机制,在性能上通常优于频繁执行的watch函数。
数据的可变性: computed 属性是只读的,它们不能被直接修改。atch 属性则可以监听数据的变化,
并且可以在回调函数中直接修改数据,或者执行其他响应数据变化的操作。
使用场景:如果你需要的是一个衍生状态,且这个状态依赖于其他数据,那么应该使用computed。
如果需要在数据变化时执行特定的逻辑或副作用操作,则应使用watch。
请简述Vue3.x 响应式数据原理是什么?
Proxy 的使用:
Vue3.x 使用 Proxy 来创建一个对象的代理,从而可以拦截对目标对象的各种操作,如读取、赋值等。
当对代理对象进行读取或赋值时,Proxy 定义的 handler 中的相应方法(如 get、set)会被触发,
Vue 可以在这些方法中实现数据的响应式处理。
数据劫持:
通过 Proxy,Vue3.x 可以直接对整个对象进行劫持,而不仅仅是对象的属性。这意味着无论是对象属性的
读取、修改,还是数组方法的调用、数组长度的改变等,都可以被 Vue 侦测到。
与 Vue2.x 相比,这解决了 Object.defineProperty 无法监听到数组下标变化的问题,以及需要递归遍历
对象属性进行劫持的缺点。
深度观测:
由于 Proxy 只会代理对象的第一层,Vue3.x 在处理深度嵌套的对象时,Reflect是ES6引入的一个内置对象,
它提供了一系列方法来操作对象,比如读取和设置属性值、删除属性等,Vue利用Reflect来进行这些操作,
以保持代码的一致性和可读性。如果是,则再通过 reactive 方法对返回的对象进行代理,从而实现了深度观测。
追踪与触发:Vue利用Proxy在访问数据时进行追踪(track),即记录下当前运行的effect(副作用函数)。
当数据改变时,通过触发(trigger)机制,通知所有依赖于此数据的effect重新执行,从而实现视图的自动更新
Effect: Vue 3引入了effect函数来替代Vue 2中的Watcher,用于定义和管理副作用。每个effect本质上
是一个收集依赖和执行更新逻辑的函数。在读取响应式数据时会自动执行并收集依赖,数据变化时再执行以更新视图。
优势:
相比 Vue2.x,Vue3.x 的响应式系统更加高效和灵活。Proxy 可以直接监听整个对象的变化,无需递归遍历
对象的属性;同时,Proxy 还有多达 13 种拦截方法,为 Vue 提供了更多的控制手段。
另外,作为新标准,Proxy 将受到浏览器厂商的重点性能优化,从而在未来可能有更好的性能表现。
工作流程
创建响应式对象:Vue使用reactive函数,内部利用Proxy包裹原始数据对象,拦截并代理对数据的操作。
数据读取:当访问响应式数据时,Proxy会触发getter,Vue在此时记录下当前正在运行的effect。
数据变更:当响应式数据被修改时,Proxy的setter会被触发,Vue会检查这个变化,并标记该数据为“脏”。
更新视图:Vue通过之前收集的依赖(effect),使用Trigger API通知所有依赖此数据的effect重新执行,
从而更新相关的DOM。
总结:
Vue3.x 的响应式数据原理基于 Proxy 对象实现,通过拦截对目标对象的操作,实现对数据的劫持和
响应式处理。与 Vue2.x 相比,Vue3.x 的响应式系统更加高效、灵活,且支持对数组和对象的深度观测。
如何理解Vue3中的模板编译原理?
模板解析:
Vue首先将模板字符串解析成一个抽象语法树(AST)。AST是一个JavaScript对象,它描述了模板的结构和内容。
这个过程通过词法分析和语法分析,将模板字符串拆分成一系列的词法单元(tokens),然后将这些词法单元组合
成一颗AST。
在解析过程中,Vue会识别模板中的原生HTML和非原生HTML元素,如如插值表达式({{ }})、指令(v-if、
v-for等)、事件监听器(@click)等,并将它们作为AST的一部分。
生成AST(抽象语法树):
Vue会根据解析出的tokens生成一个抽象语法树(Abstract Syntax Tree, AST)。AST是一种用来表示代码
结构的树状数据结构,每一个节点都代表源代码中的一个结构。在Vue中,AST节点可能代表一个元素(如div标
签)、一个文本节点、一个插值表达式、一个指令等。这个步骤是将模板的结构转化为一种更易于操作和
分析的形式。
AST优化:
Vue会对生成的AST进行一系列的遍历和转换操作,目的是优化模板结构,比如消除不必要的节点、合并静态阶级
(hoisting static nodes)、提取公共静态部分等,以提高渲染性能。此外,Vue还会在这个阶段处理指令逻
辑,将其转换为可执行的渲染函数代码片段。表达式节点优化则是对模板中的表达式进行简化或替换,以减少运行
时计算量。
生成渲染函数:
Vue会将优化后的AST转换为实际的JavaScript代码,这个代码定义了一个渲染函数(Render Function)。渲染
函数接受一个上下文对象作为参数,负责根据当前的数据状态生成虚拟DOM树(Vue 3中直接生成真实DOM更新指
令)。渲染函数中包含了模板中的指令、属性、事件等信息以及对应的操作代码,可以在运行时动态生成虚拟
DOM。
渲染函数:
Vue会将生成的渲染函数缓存起来,以便下次使用。缓存的键值是模板字符串,当数据变化时,Vue重新调用
这个函数,比较新旧虚拟DOM差异,并应用最小化更新策略到真实DOM上,实现高效的界面更新。
编译流程总结:
模板编译原理的核心是将模板转换成渲染函数,这个过程在Vue内部通过解析器、转换器和生成器三个组件来完
成。解析器负责将模板解析为AST,转换器负责将AST转换为JS抽象语法树,生成器则负责将JS抽象语法树生成
目标代码(即渲染函数)。
Vue的编译模块包括compiler-core、compiler-dom、compiler-sfc和compiler-ssr等,其中compiler-core
是编译的核心模块,与平台无关。其他模块则是在compiler-core的基础上针对不同的平台作了适配处理。
Vue的模板编译原理是一个从模板文本到可执行JavaScript代码的转换过程,涉及解析、抽象语法树生成、
优化转换、代码生成等多个阶段。
简述vue3.mixin的使用场景和原理?
mixins 选项接受一个 mixin 对象数组。这些 mixin 对象可以像普通的实例对象一样包含实例选项,
它们将使用一定的选项合并逻辑与最终的选项进行合并。
原理:
Composition Functions: 创建自定义的Composition Functions(例如使用setup函数),这些函数接收必要
的参数并返回一组状态和方法。在其他组件的setup函数中通过调用这些Composition Functions来“混入”所需的
功能。这些函数内部可以使用ref、reactive等API来管理状态,也可以直接返回方法供组件使用。
直接对象组合:在组件的setup函数中,可以直接通过解构和对象展开运算符 {...} 来组合多个对象的属性和方
法,以此来模拟混入的效果。这种方式允许你灵活地挑选和组合不同的功能模块。
使用场景:
功能模块化:通过组合函数或对象字面量,可以全局设置axios的请求拦截器和响应拦截器,或者全局添加
一些通用的方法或属性,如日期格式化、金额格式化等,便于在组件间共享和维护。
逻辑重用:当需要在多个组件中重复使用某些逻辑、样式或功能时,可以将它们抽离成mixin,然后在多个
组件中引入和使用。
解释Vue3中transition的理解?
<Transition> 是一个内置组件,这意味着它在任意别的组件中都可以被使用,无需注册。它可以将进入和
离开动画应用到通过默认插槽传递给它的元素或组件上。
<transition>依然会自动应用以下CSS类名来控制过渡动画:
v-enter-from:进入过渡开始的状态。
v-enter-active:进入过渡生效时的状态,可以用来定义动画的持续时间和曲线。
v-enter-to:进入过渡结束的状态。
v-leave-from:离开过渡开始的状态。
v-leave-active:离开过渡生效时的状态。
v-leave-to:离开过渡结束的状态。
示例:
<transition name="fade">
<div v-if="show">Hello World</div>
</transition>
<TransitionGroup>是一个内置组件,专门用于处理v-for列表中的元素或组件的插入、移除和顺序改变时的动画效
果。这个组件在构建动态列表,特别是当列表元素可能频繁添加、删除或重新排序时,特别有用。
区别:
容器元素:默认情况下,<TransitionGroup>不会渲染一个容器元素。这意味着它不会包裹其内部的元素,
而是直接让元素保持在其原始的位置。但你可以通过传入tag prop来指定一个元素作为容器元素来渲染。
过渡模式:在<TransitionGroup>中,过渡模式(如in-out或out-in)不可用,因为我们不再是在互斥的
元素之间进行切换,而是在列表元素之间进行过渡。
唯一的key属性:在<TransitionGroup>中,列表中的每个元素都必须有一个独一无二的key attribute。
这个key用于跟踪每个节点的身份,从而可以重用和重新排序现有元素。
CSS过渡class:与<Transition>不同,<TransitionGroup>的CSS过渡class会被应用在列表内的元素上,
而不是容器元素上。这意味着你可以为列表中的每个元素定义不同的过渡效果。
优化:
Teleport:虽然不是直接与<transition>相关,但Vue 3引入的<teleport>组件使得元素可以被渲染到
DOM树的其他位置,这为过渡效果的设计提供了新的场景。
Better TypeScript Support:Vue 3原生支持TypeScript,使得在编写包含<transition>的代码时
类型检查和代码提示更加精确。
简述对于Vue3的diff算法理解 ?
diff算法用于高效地比较虚拟DOM,对比新旧虚拟 DOM 树的差异,并将这些差异应用到实际的DOM上;
以尽可能地减少对真实 DOM 的操作,提高页面的性能和效率。
Fiber:Vue3引入了Fiber架构,它可以将更新过程分割成多个阶段,并让这些阶段可以被打断和重复使用,
这样做的目的是为了支持跨帧的更新,这对于实现高性能用户界面至关重要。
新的patching算法: Vue3对diff算法进行了改进,使用了基于递归的比对策略,并在此基础上加入了几个优化项,
如:key属性的利用、静态节点的缓存等。
Fragment: Vue3中的组件可以有多个根节点,这时候可以使用Fragment来包裹这些节点,最终只会渲染一个节点。
Key的作用:为每个列表项设置唯一key属性是Vue diff算法高效运行的关键。Key帮助Vue识别哪些节点是新增的、
哪些是被修改的、哪些是移动的以及哪些是需要移除的,从而避免不必要的DOM操作。Vue会优先比较具有相同key的节
点,如果key发生了变化,则认为是完全不同的元素,需要重新创建或移动DOM元素。
总结:Vue 3的diff算法基于局部更新的原则,通过同层比较、利用key来跟踪节点、采用最小变更策略以及框架
层面的其他优化,实现了高效的DOM更新机制。
请简述Vue3 的性能优化可以从哪几个方面去思考设计 ?
组件设计与复用:
合理使用 key 属性:在使用 v-for 进行列表渲染时,为每个项指定唯一的 key 属性有助于更高效地重用
和更新 DOM。
使用 keep-alive:keep-alive 是一个 Vue 内置组件,它可以在组件切换时缓存组件实例,而不是销毁它们。
这有助于减少组件的重新创建和销毁开销,并提高性能。
异步组件:Vue3支持异步组件,允许你按需加载组件。这有助于减少初始加载时的压力,并提高应用的响应速度。
优化Props传递与事件监听:
避免传递大型对象或数组作为Props,这会导致组件不必要的重新渲染。可以考虑使用计算属性或方法来
提取所需数据。
优化渲染性能
使用v-if与v-show:根据情况选择合适的条件渲染指令。v-if适用于条件较少变化的情况,减少DOM操作;
v-show则适用于频繁切换的情况,减少渲染成本。
优化图片与媒体资源:使用适当大小和格式的图片,考虑WebP等高效格式,以及懒加载策略。
其他优化策略:
使用 Composition API:Composition API 提供了一种更加灵活和可重用的方式来组织组件逻辑。通过将相关
逻辑组合在一起并使用函数式编程范式(如 hooks),你可以创建可复用的逻辑块并在多个组件之间共享它们。
懒加载与代码拆分:通过Vue的动态导入功能实现路由懒加载,以及利用Webpack等构建工具进行有效的代码拆分,
可以减少首屏加载时间,提高应用启动速度。
使用缓存:对于需要频繁计算和查询的数据,可以使用缓存来存储结果并减少计算时间
vue3通过数据劫持可以精准的探测数据变化,为什么还要进行diff检测差异?
DOM 更新优化:Vue 需要比较新旧 Virtual DOM(Vue 中用于表示真实 DOM 的轻量级、可计算的对象结构)
的差异,这个过程称为 Diff 算法。Diff 的目的是最小化实际的 DOM 操作,因为直接操作 DOM 是相对昂贵的操作。
通过比较差异,Vue 只会修改那些真正发生变化的部分,而不是每次数据变化都重新渲染整个界面。
提高效率:Diff 算法通过高效的比对策略(如深度优先搜索、两端比较等),快速定位到最小变更集,这样可以
显著减少 DOM 操作的次数,提高整体性能。
跨平台兼容性:Vue不仅可以运行在浏览器中,还可以运行在诸如服务器端渲染(SSR)和原生移动应用等环境中。
虚拟DOM作为一个抽象层,可以屏蔽不同平台下真实DOM的细节差异,使得Vue能够在不同环境中保持一致的开发体验。
状态管理与复用:Vue 应用中可能包含复杂的组件结构和状态管理,Diff 算法帮助维护这种复杂性下的高效更新,
确保状态变更与UI更新之间的准确映射,尤其是在使用 Vuex 等状态管理库时。
Vue3.0 Proxy 相比 defineProperty 的优势在哪里?
全面的拦截能力:Proxy 可以拦截更多的操作类型,包括但不限于读取(get)、设置(set)、枚举(in)、删除
(deleteProperty)、自有属性定义(defineProperty)等。这意味着 Vue3 可以对数据访问和修改进行更细粒度的控
制,支持更多类型的响应式数据,比如数组的某些方法(如push、splice)可以直接被拦截处理,而无需像
Vue2 中那样单独处理特殊-case。
对象的动态属性:使用 Object.defineProperty 需要在初始化时就定义好所有响应式属性,对于后来添加的新属性,
需要手动调用 Vue.set 方法使其变为响应式的。而 Proxy 可以自动跟踪对象上的新增属性,无需额外操作,使得响
应式系统更加灵活和自动化。
性能优化:虽然 Proxy 在某些场景下创建和代理对象的开销稍大,但在数据量大或频繁变动的场景下,由于其更灵活
的拦截机制,可以减少额外的依赖追踪和处理逻辑,从而在总体上可能带来更好的性能表现。特别是对于深层嵌套对象
的处理,Proxy 更具优势。
易于理解和维护:Proxy 拦截操作的方式更加简洁明了。特别是在处理复杂逻辑和多级嵌套数据时,Proxy 的
统一处理接口相比 defineProperty 的分散定义和处理方式,大大提升了代码的可维护性。
原生支持:Proxy 是 ES6 的一部分,是 JavaScript 原生提供的特性,这意味着它在现代浏览器和Node.js环境
中的支持度更好,无需依赖于任何外部库或特殊编译步骤。
请简述Vue3中的v-cloak的理解 ?
v-cloak是一个指令,主要用于解决Vue应用在页面加载时短暂显示原始模板代码(即未编译的Mustache语法)的问
题。
v-cloak的工作原理是:当你在一个元素上使用v-cloak指令时,Vue会为这个元素添加一个CSS样式,通常是类似
[v-cloak]{ display: none; }的规则。这个样式会隐藏元素,直到Vue实例完成编译并插入到DOM中。一旦Vue处理
完数据绑定,编译完成,v-cloak指令就会被自动移除,从而解除对该元素的隐藏,使元素及其内容正常显示。
总结:
v-cloak提供了一种方式来防止Vue应用在初始加载时闪烁原始模板代码,提升了用户体验。不过,在Vue 3中,
由于其更快的初始化速度和更新的模板编译策略,v-cloak的使用场景可能不如Vue 2中那么常见,但仍可作为解
决页面初次渲染时闪烁问题的一个选项。为了达到更好的效果,建议同时配合合适的CSS和 Vue的异步组件、
Suspense等高级特性来优化应用的加载和渲染过程。
请说明Vue3的solt的用法?
solt:它允许你在组件内部定义“占位符”,这些占位符可以在使用组件时被替换为外部传入的内容。
默认插槽:不带名称的 <slot> 被称为默认插槽。在组件中定义一个 <slot>,然后在使用该组件时,在标签
内部放入的内容会插入到这个插槽的位置。
具名插槽:你可以为 <slot> 分配一个名字,以便在组件中使用多个插槽,并在使用组件时明确指定内容应该插入哪个插槽。
作用域插槽:在slot组件上绑定name以外的属性,可以把子组件的数据传递给父组件,这种插槽叫作用域插槽,
实际上就是携带了子组件数据的插槽。
示例:
<template>
<div>
<slot name="item" v-for="item in items" :item="item"></slot>
</div>
</template>
<script setup>
const items = ref(['Item 1', 'Item 2', 'Item 3'])
</script>
<my-component>
<template v-slot:item="{ item }">
<li></li>
</template>
</my-component>
请简述vue2和vue3的区别 ?
Composition API:
Vue2 主要依赖于 Options API,即在组件中通过不同的选项(如 data, methods, computed, watch)来组织逻辑。
Vue3 引入了全新的 Composition API,通过 setup() 函数和组合函数(如 ref, reactive, computed,
watchEffect)来更灵活地组织和复用逻辑。虽然Vue3仍然支持Options API,但Composition API成为了
更推荐的编写方式。
响应式系统:
Vue2 使用 Object.defineProperty 来实现数据的响应式,这限制了它只能对已知属性进行追踪。
Vue3 则采用了 Proxy,能够监听整个对象的变化,包括数组内部数据的变化。这种改变使得Vue3在响应式
系统的性能和效率上有所提升。
Template Refs:
Vue2 中通过 $refs 访问DOM元素或子组件实例,但它是非响应式的且仅在mounted和updated钩子中可用。
Vue3 改进了 ref API,使其既可用于模板中获取DOM引用,也可用于创建响应式引用,且在
Composition API中更加方便使用。
支持碎片化和指令:
Vue3 支持 Fragments,允许一个组件返回多个根节点,而Vue2中每个组件只能有一个根节点。
Vue3 还移除了一些过时的指令(如 v-bind.sync 被 v-model 的新语法取代),并引入了新的指令,
如用于事件监听的 .once 和 .stop。
TypeScript支持:
Vue3对TypeScript的支持更加友好,提供了更好的类型推断和类型检查,使得开发过程更加安全可靠。
Vue2虽然也可以使用TypeScript,但需要额外的配置和声明文件。
虚拟DOM处理:
Vue3 在 diff 算法中相比 Vue2 增加了静态标记,其作用是为了会发生变化的地方添加一个 flag 标记,
下次发生变化的时候直接找该地方进行比较。采用同序列比对,和最长递归子序列的算法,来计算出最小的
修改偏移量。
性能优化:
Vue3 新增了 <teleport> 组件,允许将组件内容渲染到DOM树的其他部分,这对于弹窗、提示等需要脱离
当前组件层级渲染的场景非常有用。Vue2没有内置这样的功能。
Vue3 引入了 <suspense> 组件,用于异步组件的加载占位及错误边界处理,提高了代码的组织性和错误处
理能力。Vue2中异步组件的加载和错误处理较为基础,没有专门的 Suspense 组件。
简述Vue3初始化过程中(new Vue(options))都做了什么?
创建应用实例: createApp(App) 首先会创建一个Vue应用实例。这个过程中,Vue会分析传递给它的根组件App,
解析其模板、脚本和样式。
组件初始化与编译:
模板编译: 如果组件使用了模板,Vue会编译模板为Render Function。这个过程包括解析模板语法、
生成虚拟DOM描述、收集静态树信息等。
响应式系统建立: Vue会通过Proxy(在Vue3中)或Object.defineProperty(如果使用了兼容模式)来
使数据变得可响应,为组件的状态创建getter和setter,以便在数据变化时能触发视图更新。
Setup函数执行: 如果组件使用了Composition API,Vue会执行setup()函数。在这个阶段,组件的状态会
被初始化,使用ref、reactive等创建响应式数据,以及定义计算属性、侦听器等。
创建Renderer: Vue会基于当前环境选择合适的渲染器(如Web Renderer或Server Renderer)。渲染器负责
将虚拟DOM转换为真实DOM并挂载到页面上。
挂载应用: mount('#app') 会找到指定的挂载点,并开始渲染过程。Vue会执行根组件的Render Function,
构建初始的DOM树,并将其插入到页面中指定的位置。
生命周期钩子: 在挂载过程中,Vue会执行相关生命周期钩子函数,如beforeMount、mounted等,允许用户在
特定时刻介入执行自定义逻辑。
更新与渲染: 当组件状态变化时,Vue会通过其高效的Diff算法计算出最小变更集,然后只更新必要的DOM节点,
这一过程涉及beforeUpdate、updated等生命周期钩子。
事件处理与优化: Vue会处理组件上的事件绑定,确保事件监听器的高效注册与解绑,同时,对于
使用.once、.stop等修饰符的事件也会做相应处理。
简述为什么Vue3采用异步渲染 ?
Vue2 中就已使用nextTick来调度DOM更新操作,它确保所有的数据变化在DOM更新之前完成,这是通过微任务
(如Promise.resolve().then(...))实现的,可以视为一种简单的异步调度方式。
Vue3 对这一机制进行了改进,引入了更精细的异步队列管理。Vue3的核心渲染机制主要包括组件的创建、
更新和销毁等过程。当数据变化触发重新渲染时,Vue3 不会立即执行DOM更新,而是将这些变更记录在一个队列中。
这个队列的处理(flushing)会在微任务队列清空后执行,这样可以批量处理多个状态变更,减少不必要的DOM操作,
提高性能。
优点:
批量更新: 通过累积一定数量的变化后再统一处理,Vue3 能够减少DOM操作的次数,从而提高性能。例如,
如果在同一个事件循环中有多个状态变更,它们会被合并成一次更新。
避免不必要的计算: 在更新之前,Vue3 有机会通过新的依赖跟踪系统识别哪些组件确实需要更新,
忽略那些状态变更并未导致实际UI变化的组件。
提升用户体验: 批量更新减少了界面闪烁和重绘的频率,使得应用看起来更加流畅。
更好的资源利用: 异步处理让主线程有更多时间处理其他任务,比如用户输入事件,从而提高应用的
整体响应速度。
Vue 3.0 所采用的 Composition Api 与 Vue 2.x使用的Options Api 有什么区别?
逻辑复用:
Options API:逻辑复用主要通过mixins实现,但这种方式容易导致命名冲突,且难以追踪数据流和方法的来源。
Composition API:通过组合函数(setup())可以更清晰地复用和组合逻辑,避免了mixins的缺点。
你可以从多个函数中“组合”需要的功能,使得代码更加模块化和易于维护。
代码组织:
Options API:数据、计算属性、方法、生命周期钩子等分散在不同的选项对象中,对于大型项目,
这可能导致组件配置变得冗长且难以阅读。
Composition API:通过使用 setup 函数和 ref、reactive 等 API,使得逻辑更加模块化,
更容易在其他地方重用
响应式:
Options API:依赖于this.$data和this.$props的隐式响应式系统。
Composition API:引入了ref和reactive等API来显式创建响应式数据,使得响应式逻辑更加直观和可控。
生命周期钩子:
Options API:使用经典的生命周期钩子函数,如created, mounted, updated等。
Composition API:虽然也支持部分经典生命周期钩子,但更推荐使用组合函数内的onBeforeMount,
onMounted, onUpdated, onUnmounted等组合式API,它们提供了更细粒度的控制和更好的组合能力。
状态管理:
Options API:与Vuex集成时,直接在组件的计算属性或methods中使用this.$store。
Composition API:通过useStore()等Composition函数更容易地与Vuex等状态管理库集成,
进一步促进逻辑的解耦和重用
请问什么是SSR ,它主要解决什么问题?
Server-Side Rendering 我们称其为SSR,意为服务端渲染。与传统的客户端渲染(CSR,Client-Side
Rendering)相对。在 SSR 模式下,网页的初始 HTML 内容是在服务器端生成的,然后将其发送到浏览器,
而不仅仅是发送一个空的HTML壳(如只有一个<div id="app"></div>)加上一堆JavaScript代码让浏览器
去执行并渲染页面。
首屏加载速度与SEO优化:
首屏加载:对于客户端渲染的应用,用户首次访问时需要下载JavaScript文件,然后执行渲染,这可能导致白屏时
间较长。SSR 则能在服务器端预先渲染好静态的HTML,用户首次请求时即可看到完整的页面内容,从而加快了首屏
加载速度。
SEO友好:搜索引擎爬虫通常不会执行JavaScript,因此客户端渲染的页面可能无法被正确索引。SSR 生成的服务
器端静态内容可直接被搜索引擎抓取,有助于提高网站的搜索引擎优化(SEO)。
统一的心智模型:
你可以使用相同的语言以及相同的声明式、面向组件的心智模型来开发整个应用,而不需要在后端模板系统和前端
框架之间来回切换。
优化用户体验:
对于低性能设备或网络条件不佳的用户,SSR 减轻了客户端的渲染负担,使得应用加载更快,体验更流畅。
特别是在移动端或老设备上,客户端的CPU和内存资源有限。通过在服务器端完成大部分渲染工作,可以减少客户
端的计算压力。
易于分享和预览:
由于服务器端直接生成可浏览的HTML内容,用户可以更容易地分享页面链接,并且通过链接预览(如社交媒体或即
时消息中的链接预览功能)能正确展示页面内容。
请解释Vue为什么要用虚拟Dom ,详细解释原理 ?
Vue使用虚拟DOM(Virtual DOM)作为其核心机制之一,以提高用户界面的更新效率和性能。
性能优化
减少DOM操作:直接操作DOM的性能是较低的,因为DOM的每一次变动都可能触发浏览器的重排(reflow)和
重绘(repaint)。而JavaScript层的操作效率相对较高。通过将DOM操作转化为JavaScript对象的操作,
Vue可以利用虚拟DOM来提高性能。
优化渲染过程:当Vue中的数据发生变化时,Vue会先使用虚拟DOM进行计算和比较,然后才会将变化的部分
更新到真实的DOM中。这样,Vue可以避免不必要的DOM操作,从而提高页面的渲染效率。
跨平台能力:由于虚拟DOM是平台无关的,它不仅可以在Web环境中操作DOM,还可以在其他环境(如Weex用于
构建原生移动应用)中映射为相应平台的UI组件,增强了框架的灵活性和可移植性。
工作原理
用JavaScript对象模拟真实DOM树:虚拟DOM是一个轻量级的JavaScript对象,它对应着真实的DOM结构。
每一个虚拟DOM节点都是一个VNode(Virtual Node)对象,它包含了真实DOM节点的所有信息,如标签名、
属性、子节点等。
差异比较(Diffing):Vue使用高效的算法(如基于启发式的、带有key的列表比较算法),Vue会使用diff算法
来比较旧的虚拟DOM树和新的虚拟DOM树之间的差异。diff算法会找出需要更新的最小节点集,并生成一个
patch对象来描述这些差异。
patch算法:最后,Vue会使用patch算法将patch对象应用到真实的DOM树上,从而完成视图的更新。
这个过程是对比新旧虚拟节点之间有哪些不同,然后根据对比结果找出需要更新的的节点进行更新。
vuex与pinia的区别?
Vuex
官方库:Vuex 是Vue.js官方推出的状态管理库,专门为Vue应用设计,特别适合大型单页应用(SPA)
的状态管理。
严格模式:Vuex 强调一种严格的管理状态的模式,包括State(状态)、Getters(获取状态的方法)、
Mutations(用于改变状态的同步方法)、Actions(处理异步逻辑并提交Mutation的方法)。这种模式
要求所有状态变更必须通过Mutation来完成,确保状态更改的可追踪性。
模块化:Vuex 支持通过模块来组织状态,拥有庞大的生态系统,适合大型项目中状态的分块管理。
Vue 2 & 3 支持:Vuex 被设计为同时支持Vue 2和Vue 3,但Vue 3环境下推荐使用Vuex 4版本。
缺点:Vuex 的概念比较复杂,因此学习曲线比较陡峭。Vuex 在处理一些简单的状态管理需求时可能会有些繁琐,
因为它需要使用一些复杂的概念和 API。
Pinia
社区驱动:Pinia是专门为Vue 3设计的状态管理库,与Vue 3的响应式系统和Composition API紧密集成。
它借助Composition API的能力提供了更直观和简洁的状态管理方式。Pinia使用类似于Vue组件的方式来定义
和组织状态,并使用辅助函数和装饰器来访问和操作状态。
简化:相比于Vuex,Pinia的API设计更加简洁直观,降低了入门门槛。它不强制使用Mutation,
而是允许直接在Action中修改状态,更符合直觉。
TypeScript友好:Pinia从一开始就内置了对TypeScript的优秀支持,提供了丰富的类型信息,
使得状态管理更加类型安全。
更轻量:Pinia的设计理念倾向于轻量和灵活,更适合现代前端开发,尤其是中、小型项目。
自动状态快照:Pinia提供了状态快照功能,便于调试,可以查看状态的历史变化,无需额外配置。
Store结构:Pinia的核心概念是Stores,每个Store代表一个独立的状态管理单元,可以独立导出和测试,
使得状态管理更加模块化和易于维护。
缺点:Pinia 是一个相对较新的状态管理库,因此它可能存在一些未知的问题和限制。由于 Pinia
是一个相对较新的库,它的生态系统可能不够完善,因此可能需要花费更多的时间来解决问题。
总结
选择依据:如果你的项目是Vue 3,并且希望状态管理更加简单、灵活,或者项目对TypeScript支持有较高要求,
那么Pinia可能是更好的选择。而对于已经有Vuex基础且维护大型Vue 2应用的团队,继续使用Vuex也是一个稳定
的选择。
设计理念:Vuex强调规范化和中心化管理,适合大型团队和复杂应用;Pinia则侧重于简化和开发者体验,
更适合快速开发和中、小型项目。
vue3组件间通信,有哪些?
Props & Emits:
最基本的方式,父组件通过Props向下传递数据给子组件,子组件通过 $emit 触发事件通知父组件。
Vue3 中可以使用 emits 选项或 defineEmits 函数来定义可触发的事件。
Provide / Inject:
用于祖先组件向后代组件注入数据,不局限于直接父子关系。Vue3 中依旧支持这种方式,但推荐使用更灵活的
Composition API中的 provide 和 inject 函数。
Event Bus(事件总线):
创建一个全局的Vue实例作为事件中心,任何组件都可以通过它来发布/订阅事件,实现跨级组件间的通信。
虽然可行,但在Vue3中更推荐使用Composition API结合mitt等轻量库来实现类似功能。
Vuex:
用于管理应用的全局状态。当多个组件需要共享状态时,使用Vuex可以集中存储和管理状态,通过mapState,
mapGetters, mapActions, mapMutations或直接使用useStore来访问和修改状态。
pinia:
Pinia 是一个专门为Vue.js设计的状态管理库,它提供state:存储数据的仓库,getters:获取和过滤数据
(跟 computed 有点像),actions:存放 “修改 state ”的方法。在使用Pinia时,可以轻松地创建定义状态
的存储,然后将其与Vue组件绑定,使它们能够使用该状态;一般用来处理跨组件通信。
Composition API的自定义Hook:
Vue3 引入的Composition API允许创建可复用的逻辑片段,你可以创建自定义Hook来封装跨组件共享的功能
或状态管理逻辑,从而实现组件间的一种间接通信。
Teleport(虽然不是直接的通信方式):
Vue3 新增的<teleport>组件可以用来在DOM的不同部分渲染组件,虽然它主要用于布局,但在某些场景下,
可以通过这种方式间接实现组件间内容的“传输”和布局上的通信效果。
Reactivity APIs:
Vue3 的Reactivity系统(如ref, reactive, computed)提供了更底层的响应式数据管理能力,
可以在不直接依赖组件实例的情况下,创建和共享响应式数据,适用于更复杂的数据共享和通信场景。