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

前端Vue.js面试题(4)

✨✨✨目录

 1.Vuex的原理?

2.Vuex和localStorage的区别?

3.Redux和Vuex有什么区别,它们有什么共同思想吗?

4.Vuex中的辅助函数怎么使用?

5.Vue3有什么更新?

6.Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?

7.对虚拟DOM的理解?

8.为什么需要虚拟DOM?

9.虚拟DOM一定更快吗?

10.说说Vue中的diff算法?

11.说说Vue中,key的原理?

12.Vue初始化页面闪动问题?

13.extend有什么作用?


 1.Vuex的原理?

Vuex是一种状态管理模式,用于管理应用程序的所有组件的状态。存在的目的是共享可复用的组件状态。

Vuex的集中属性及存在的意义:

(1)State(状态):应用程序的数据存储在一个单一的状态树中,即state。这个状态树是响应式的,当状态发生变化时,相关的组件将自动更新。

(2)Getter(获取器)getter允许从state中派生出一些衍生的状态,类似于计算属性。可以使用getter来对state进行处理和计算,并将其暴露给组件使用。

(3)Mutation(突变)mutation是用于修改state的唯一途径。它定义了一些操作函数,每个函数都有一个特定的名称(称为type),并且可以在这些函数中改变state的值。mutation必须是同步的,以确保状态变更是可追踪的。

(4)Action(动作)action用于处理异步操作和复杂的业务逻辑。类似于mutation,但action可以包含异步操作,可以在action中触发多个mutation,也可以在action中调用其他action

(5)Module(模块):为了更好地组织和拆分大型的应用程序,Vuex允许将stategettermutationaction划分为模块。每个模块都有自己的stategettermutationaction,并且可以被嵌套和组合。

2.Vuex和localStorage的区别?

vuex存储在内存中,localstorage以文件的方式存储在本地;vuex用于组件之间传值,localstorage存储在浏览器中,一般是在跨页面传递数据时使用;Vuex能做到数据的响应式,localstorage不能;刷新页面时vuex存储的值会丢失,localstorage不会。

3.Redux和Vuex有什么区别,它们有什么共同思想吗?

相同点:

  • state共享数据
  • 流程一致:定义全局state,触发,修改state
  • 原理相似,通过全局注入store

不同点:

实现原理上来说:

  • Redux 使用的是不可变数据,而Vuex的数据是可变的。Redux每次都是用新的state替换旧的state,而Vuex是直接修改
  • Redux 在检测数据变化的时候,是通过 diff 的方式比较差异的,而Vuex其实和Vue的原理一样,是通过 getter/setter来比较的

表面层来说:

  • vuex定义了state、getter、mutation、action四个对象;redux定义了state、reducer、action。
  • vuex中state统一存放,方便理解;reduxstate依赖所有reducer的初始值。
  • vuex有getter,目的是快捷得到state;redux没有这层,react-redux mapStateToProps参数做了这个工作。
  • vuex中mutation只是单纯赋值(很浅的一层);redux中reducer只是单纯设置新state(很浅的一层)。他俩作用类似,但书写方式不同。
  • vuex中action有较为复杂的异步ajax请求;redux中action中可简单可复杂,简单就直接发送数据对象({type:xxx, your-data}),复杂需要调用异步ajax(依赖redux-thunk插件)。
  • vuex触发方式有两种commit同步和dispatch异步;redux同步和异步都使用dispatch。

4.Vuex中的辅助函数怎么使用?

在实际开发中,我们经常会用到 vuex 来对数据进行管理,随着数据越来越多,我们逐渐开始使用一些语法糖来帮助我们快速开发。 即 vuex 中的 mapState、mapGetters、mapMutations、mapActions 等辅助函数是我们经常使用到的。

mapState:把state属性映射到computed身上

computed:{...Vuex.mapState({input:state=>state.inputVal,n:state=>state.n})   
}

mapAcions:把actions里面的方法映射到methods中

methods:{...Vuex.mapActions({add:"handleTodoAdd",    //val为actions里面的方法名称change:"handleInput"     })}

mapMutations:把mutations里面的方法映射到methods中

methods:{...Vuex.mapMutations({handleAdd:"handlMutationseAdd"})}

mapGetters:把getters属性映射到computed身上

 computed:{...Vuex.mapGetters({NumN:"NumN"})}

modules属性: 模块

把公共的状态按照模块进行划分

  • 每个模块都相当于一个小型的Vuex
  • 每个模块里面都会有state getters actions mutations
  • 切记在导出模块的时候加一个 namespaced:true 主要的作用是将每个模块都有独立命名空间
  • namespace:true在多人协作开发的时候,可能子模块和主模块中的函数名字会相同,这样在调用函数的时候,相同名字的函数都会被调用,就会发生问题。为了解决这个问题,导出模块的时候要加namespace:true.

5.Vue3有什么更新?

Vue 3相比Vue 2在多个核心领域实现了升级,主要差异如下:

响应式系统重构

Vue 3 采用 Proxy 替代 Vue 2 的Object.defineProperty ,解决了无法检测数组索引/对象新增属性的问题,并优化了深层嵌套对象的性能。 ‌

Composition API 引入

通过setup函数替代传统 Options API ,支持逻辑复用与组件拆分,解决了 Vue 2中逻辑分散的问题。 ‌

性能优化

  • 重写虚拟 DOM 算法(静态标记提升、区块树优化)
  • 编译时优化(Tree-shaking技术减少打包体积41%)
  • 运行时效率提升

新特性支持

  • 多根节点组件 (Fragment)
  • 跨组件渲染 (Teleport)
  • 异步组件加载状态 (Suspense) ‌

TypeScript 集成

Vue 3源码用 TypeScript 重构,提供更好的类型推断支持,而 Vue 2对TypeScript支持较弱。

生命周期调整

新增 onBeforeUnmount等更语义化的API,兼容 Vue 2生命周期钩子。

6.Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?

在 Vue 3.0 中,使用 Proxy API 替代 defineProperty API 是为了改进响应式系统的性能和功能:

(1)性能提升:Proxy API 比 defineProperty API 在许多情况下具有更好的性能。defineProperty 使用 Object.defineProperty 方法来拦截对象属性的访问和修改,但它需要遍历每个属性进行拦截。而 Proxy API 允许拦截整个对象,可以更高效地捕获对对象的访问和修改。

(2)更全面的拦截能力:Proxy API 提供了更多的拦截方法,比 defineProperty API 更灵活、丰富。它支持拦截目标的各种操作,包括读取、设置、删除、枚举等,甚至还可以拦截函数调用和构造函数实例化。

(3)更好的数组变化检测:Vue 3.0 使用 Proxy API 改善了数组的变化检测机制。Proxy 可以直接拦截数组的索引访问和修改,使得对数组的变化更容易被监听到,从而提供了更可靠的响应式行为。

(4)更易于处理嵌套对象:Proxy API 能够递归地拦截对象的嵌套属性,而 defineProperty 无法自动递归处理嵌套对象。这使得在 Vue 3.0 中处理嵌套对象更加简单和方便。

(5)更好的错误提示:相比于 defineProperty,Proxy API 提供了更好的错误追踪和调试信息。当使用 Proxy API 时,如果访问或修改了一个不存在的属性,会直接抛出错误,从而更容易发现和修复问题。

7.对虚拟DOM的理解?

从本质上来说,VirtualDOM是一个JavaScript对象,通过对象的方式来表示DOM结构。将页面的状态抽象为Js对象的形式,配合不同的渲染工具,使跨平台渲染成为可能。通过事务处理机制,将多次DOM修改的结果一次性的更新到页面上,从而有效的减少页面渲染的次数,减少修改DOM的重绘重排次数,提高渲染性能。

虚拟DOM是对DOM的抽象,这个对象是更加轻量级的对DOM的描述。它设计的最初目的,就是更好的跨平台,比如Node.js就没有DOM,如果想实现SSR,那么一个方式就是借助虚拟DOM,因为虚拟DOM本身是js对象。在代码渲染到页面之前,Vue会把代码转换成一个对象(虚拟DOM)。以对象的形式来描述真实DOM结构,最终渲染到页面。在每次数据发生变化前,虚拟DOM都会缓存一份,变化之时,现在的虚拟DOM会与缓存的虚拟DOM进行比较。在vue内部封装了diff算法,通过这个算法来进行比较,渲染时修改改变的变化,原先没有发生改变的通过原先的数据进行渲染。

另外现代前端框架的一个基本要求就是无须手动操作DOM,一方面是因为手动操作DOM无法保证程序性能,多人协作的项目中如果review不严格,可能会有开发者写出性能较低的代码,另一方面更重要的是省略手动DOM操作可以大大提高开发效率。

8.为什么需要虚拟DOM?

DOM是很慢的,其元素非常庞大,页面的性能问题,大部分都是由DOM操作引起的真实的DOM节点,哪怕一个最简单的div也包含着很多属性,可以打印出来直观感受一下: 

由此可见,操作DOM的代价仍旧是昂贵的,频繁操作还是会出现页面卡顿,影响用户的体验

举个例子:你用传统的原生apijQuery去操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。

当你在一次操作时,需要更新10个DOM节点,浏览器没这么智能,收到第一个更新DOM请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程。

而通过VNode,同样更新10个DOM节点,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性attachDOM树上,避免大量的无谓计算。

9.虚拟DOM一定更快吗?

虚拟DOM可以在某些情况下性能,但并不是绝对的。以下是一些虚拟DOM可能带来性能提升的情况:

批量更新:虚拟DOM可以将多个DOM操作合并为一次更新。它会在内部进行比较和计算,找出最小的变更集,并批量应用于真实的DOM树。这种批量更新可以减少浏览器的重排和重绘,从而提高性能。

局部更新:通过比较新旧虚拟DOM树,只有发生变化的部分会被重新渲染到真实的DOM中,而不需要重新渲染整个组件。这可以避免不必要的DOM操作,减少性能开销。

跳过昂贵的计算:在虚拟DOM的比较过程中,可以通过判断节点是否相同来跳过昂贵的计算或渲染步骤。如果两个节点相同,则无需进一步比较其子节点,从而节省了计算资源。

跨平台支持:虚拟DOM与底层平台无关,因此它可以在不同环境(例如浏览器、移动端、服务器端)进行渲染。这种可移植性使得使用虚拟DOM能够更轻松地在不同平台之间共享和重用代码。

然而,虚拟DOM也可能引入一些性能开销:

额外的内存占用:在运行时,虚拟DOM需要维护一个表示整个组件树的数据结构,这可能会占用额外的内存。

操作的复杂度:虚拟DOM需要进行比较、计算和递归遍历等操作,这可能导致一些额外的计算开销。

总的来说,虚拟DOM通常可以在中等到大型规模的应用程序中提供性能优势。然而,在简单的应用程序或特定场景下,手动的DOM操作可能更加高效。因此,在选择是否使用虚拟DOM时,需要权衡应用程序的需求、性能要求以及代码的可维护性。

10.说说Vue中的diff算法?

diff算法是一种通过同层的树节点进行比较的高效算法。diff 算法在很多场景下都有应用,在 vue 中作用于虚拟 dom 渲染成真实 dom 的新旧 VNode 节点比较。

两个特点:

  • 比较只会在同层级进行, 不会跨层级比较
  • 在diff比较的过程中,循环从两边向中间比较

比较方法:

diff整体策略:深度优先,同层比较

(1)比较只会在同层级进行,不会跨层级比较

(2)比较的过程中,循环从两边向中间收拢

举例说明diff算法更新:

新旧VNode节点如下图所示:

第一次循环后,发现旧节点D与新节点D相同,直接复用旧节点D作为diff后的第一个真实节点,同时旧节点endIndex移动到C,新节点的 startIndex 移动到了 C

第二次循环后,同样是旧节点的末尾和新节点的开头(都是 C)相同,同理,diff 后创建了 C 的真实节点插入到第一次创建的 B 节点后面。同时旧节点的 endIndex 移动到了 B,新节点的 startIndex 移动到了 E

第三次循环中,发现E没有找到,这时候只能直接创建新的真实节点 E,插入到第二次创建的 C 节点之后。同时新节点的 startIndex 移动到了 A。旧节点的 startIndex 和 endIndex 都保持不动

第四次循环中,发现了新旧节点的开头(都是 A)相同,于是 diff 后创建了 A 的真实节点,插入到前一次创建的 E 节点后面。同时旧节点的 startIndex 移动到了 B,新节点的 startIndex 移动到了 B

第五次循环中,情形同第四次循环一样,因此 diff 后创建了 B 真实节点 插入到前一次创建的 A 节点后面。同时旧节点的 startIndex 移动到了 C,新节点的 startIndex 移动到了 F

新节点的 startIndex 已经大于 endIndex 了,需要创建 newStartIdx 和 newEndIdx 之间的所有节点,也就是节点F,直接创建 F 节点对应的真实节点放到 B 节点后面

11.说说Vue中,key的原理?

在Vue中,key是用于帮助Vue识别和跟踪虚拟DOM变化的特殊属性。当Vue更新渲染真实DOM时,它使用key属性来比较新旧节点,并尽可能地复用已存在的真实DOM节点,以提高性能。

Vue 在进行虚拟 DOM 的 diff 算法时,会使用 key 来匹配新旧节点,以确定节点的更新、移动或删除。它通过 key 属性来判断两个节点是否代表相同的实体,而不仅仅是根据它们的内容是否相同。这样可以保留节点的状态和避免不必要的 DOM 操作。

key 的工作原理如下:

  • 当Vue更新渲染真实DOM时,它会对新旧节点进行比较,找出它们之间的差异。
  • 如果两个节点具有相同的key的值,则Vue认为它们是相同的节点,会尝试复用已存在的真实DOM节点。
  • 如果节点具有不同的key的值,Vue会将其视为不同的节点,并进行适当的更新、移动或删除操作。

使用 key 可以提供更准确的节点识别和跟踪,避免出现一些常见的问题,比如在列表中重新排序时导致的元素闪烁、输入框内容丢失等。

key 必须是唯一且稳定的,最好使用具有唯一标识的值,例如使用数据的唯一 ID。同时,不推荐使用随机数作为 key,因为在每次更新时都会生成新的 key,导致所有节点都重新渲染,无法复用已有的节点,降低性能。使用index作为key和没写基本上没区别,因为不管数组的顺序怎么颠倒,index都是0,1,2.这样排列,导致Vue会复用错误的旧子节点,做很多额外的工作。

12.Vue初始化页面闪动问题?

使用vue开发时,在vue初始化之前,由于div是不归vue管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于{message}的字样,虽然一般情况下这个时间很短暂,但是还是有必要让解决这个问题的。

<div v-cloak>{{ message }}
</div>
<style>[v-cloak] {display: none;}
</style>

13.extend有什么作用?

在前端开发中,extend主要有以下作用:

代码复用与组件扩展

通过extend可以扩展组件功能或创建可复用的代码模块,例如:

  • ‌组件模板继承‌:基于现有组件模板扩展新功能,避免重复编写相同代码
  • ‌插件开发‌:封装常用功能为插件,便于跨项目复用
import Vue from 'vue';
import BaseComponent from './BaseComponent.vue';
const ExtendedComponent = Vue.extend({extends: BaseComponent,data() { return { newProperty: 'This is a new property' } },methods: { newMethod() { console.log('This is a new method'); } }
});

简化CSS维护

在CSS预处理器(如Less)中,extend用于共享样式代码,避免重复编写相同属性,提升代码整洁性和可维护性。

.button-basic {border: none;padding: 15px 30px;cursor: pointer;
}
.button-report {@extend .button-basic;background-color: red;
}
.button-submit {@extend .button-basic;background-color: green;color: white;
}

对象功能扩展

通过扩展对象属性或方法实现功能增强,例如:

  • 合并多个配置对象(如Vue混入mixins) 
  • 继承基类并添加新功能(如后端开发中的类扩展)

 💕💕💕持续更新中...... 
 若文章对你有帮助,点赞❤️、收藏⭐加关注➕吧!


文章转载自:
http://atopy.gbfuy28.cn
http://beaune.gbfuy28.cn
http://biocellate.gbfuy28.cn
http://captain.gbfuy28.cn
http://chigetai.gbfuy28.cn
http://bivalence.gbfuy28.cn
http://cashmerette.gbfuy28.cn
http://charioteer.gbfuy28.cn
http://artisanate.gbfuy28.cn
http://bidialectism.gbfuy28.cn
http://chawl.gbfuy28.cn
http://caffeinism.gbfuy28.cn
http://bedbug.gbfuy28.cn
http://bfr.gbfuy28.cn
http://advisee.gbfuy28.cn
http://annunciatory.gbfuy28.cn
http://cantilever.gbfuy28.cn
http://bronchoscopy.gbfuy28.cn
http://caddo.gbfuy28.cn
http://cabby.gbfuy28.cn
http://chirm.gbfuy28.cn
http://calefaction.gbfuy28.cn
http://alertness.gbfuy28.cn
http://carmarthenshire.gbfuy28.cn
http://alternation.gbfuy28.cn
http://basal.gbfuy28.cn
http://atoxic.gbfuy28.cn
http://bullyrag.gbfuy28.cn
http://africander.gbfuy28.cn
http://autoeroticism.gbfuy28.cn
http://www.dtcms.com/a/281149.html

相关文章:

  • 超详细 anji-captcha滑块验证springboot+uniapp微信小程序前后端组合
  • 如何定义一个只能在堆上或栈上生成对象的类
  • Python初学者笔记第十二期 -- (集合与字典编程练习题)
  • U-Boot 中增加 GIC-400中断服务程序
  • Copula理论:覆盖相关性分析、极值相依性、回归建模、时间序列预测、贝叶斯网络,R/Python双语言实现+AI编程辅助(科研绘图与结果呈现)
  • Nestjs框架: 数据库多租户模式与动态模块初探
  • Oracle日期时间函数说明及与MySql区别说明
  • 同济医院R语言训练营第三期开讲!上交大张维拓老师主讲
  • RabbitMQ工作流程
  • SQL学习记录01
  • 15.图像 模板轮廓检测
  • 李白周游记50篇
  • linux-develop
  • 基于Alpine构建MySQL镜像
  • 第二阶段-第二章—8天Python从入门到精通【itheima】-129节(MySQL的安装)
  • 【前后端】Node.js 模块大全
  • 巨坑检查无误还报错is not mapped MappingException: Unknown entity:@Entity
  • DeepSWE:通过强化学习扩展训练开源编码智能体
  • 多层 `while` 循环中,`break` 的行为
  • ES2023 新特性解析_数组与对象的现代化操作指南
  • 二分查找栈堆
  • 【C语言进阶】字符函数和字符串函数的内部原理
  • “ModuleNotFoundError“深度解析:Python模块导入问题的终极指南
  • PHP语言基础知识(超详细)第二节
  • OSPFv3中LSA参数
  • dbever 导出数据库表的建表语句和数据插入语句
  • 嵌入式Linux:进程间通信机制
  • AJAX 开发中的注意点
  • ASRPRO系列语音模块(第十天)
  • AI 增强大前端数据加密与隐私保护:技术实现与合规遵