2024前端面试题集(含答案)之Vue篇

01、vue2的双向绑定原理

vue2是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

1、需要 observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter,这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。

2、compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。

3、Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要做的事情是:1、在自身实例化时往属性订阅器(dep)里面添加自己;2、自身必须有一个 update()方法;3、待属性变动 dep.notice()通知时,能调用自身的update()方法,并触发 Compile 中绑定的回调,则功成身退。

4、MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通过 Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model 变更的双向绑定效果。

02 vue2的生命周期

总共分为 8 个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

1、在 beforeCreated阶段,vue 实例的挂载元素$el 和数据对象 data 都为 undefined,还未初始化。

2、在 created 阶段,vue 实例的数据对象 data 有了,$el 还没有。

3、载入前/后:在 beforeMount 阶段,vue 实例的$el 和 data 都初始化了,但还是挂载之前为虚拟的 dom节点,data.message 还未替换。

4、在 mounted 阶段,vue 实例挂载完成,data.message 成功渲染。

5、更新前/后:当 data 变化时,会触发 beforeUpdate 和 updated 方法。

6、销毁前/后:在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 vue实例已经解除了事件监听以及和 dom 的绑定,但是 dom 结构依然存在。

03 封装vue组件的过程

首先,封装组件可以提升整个项目的开发效率,减少代码冗余,提高性能,同时便于项目模块的维护。能够把组件抽离成多个相对独立的模块,解决了传统项目开发效率低、难维护、复用性低等问题。

1、分析需求:确定业务需求,把页面中可以复用的结构,样式以及功能,单独抽离成一个.vue 文件,实现复用。

2、具体步骤:

① 注册子组件(可以是全局组件,也可以是局部组件)。

② 子组件需要数据,子组件需要使用 props 来接收数据(对,没错,就是父组件向子组件传数据的步骤),父组件进行属性绑定传递数据;

③ 如果需要给父组件传入模板,则定义插槽 slot ,将子组件的模板通过插槽渲染给父组件;

④ 如果想要在父组件中操作子组件中的数据,则需要在子组件中的 slot 标签上进行属性绑定,然后在父组件中定义 template 标签,并在标签上书写 v-slot:default=“你随便定义的名字”,然后在 template 标签中使用{{你定义的名字.子组件中绑定的属性名}}就可以了。

⑤ 如果需要在父组件中触发子组件的事件,则在子组件使用 this.$emit 将事件传递到父组件,父组件再进行事件绑定就可以(没错,就是子组件向父组件传数据的方式)。

⑥ 如果需要在父组件中触发子组件 methods 中的方法,则需要通过 ref 获取到子组件的实例,再调用子组件 methods。

04 对使用vue的理解

Vue 是一个构建数据驱动的渐进性框架,它的目标是通过 API 实现响应数据绑定和视图更新。

优点:

1、数据驱动视图,对真实 dom 进行抽象出 virtual dom(本质就是一个 js 对象),并配合 diff 算法、响应式和观察者、异步队列等手段以最小代价更新 dom,渲染页面;

2、组件化,组件用单文件的形式进行代码的组织编写,使得我们可以在一个文件里编写 html\css(scoped 属性配置 css 隔离)\js 并且配合 Vue-loader 之后,支持更强大的预处理器等功能;

3、强大且丰富的 API 提供一系列的 api 能满足业务开发中各类需求;

4、由于采用虚拟 dom,让 Vue ssr 先天就足;

5、生命周期钩子函数,选项式的代码组织方式,写熟了还是蛮顺畅的,但仍然有优化空间(Vue3 composition-api);

6、生态好,社区活跃。

缺点:

1、由于底层基于 Object.defineProperty 实现响应式,而这个 api 本身不支持 IE8

及以下浏览器;

2、由于百度等搜索引擎爬虫无法爬取 js 中的内容,故 spa 先天就对 seo 优化心

有余力不足。

05 虚拟Dom的理解

虚拟 dom 是相对于浏览器所渲染出来的真实 dom 的,在 react,vue 等技术出现之前,我们要改变页面展示的内容只能通过遍历查询 dom 树的方式找到需要修改的 dom 然后修改样式行为或者结构,来达到更新 ui 的目的。

这种方式相当消耗计算资源,因为每次查询 dom 几乎都需要遍历整颗 dom 树,如果建立一个与 dom 树对应的虚拟 dom 对象( js 对象),虚拟DOM 表现为一个 Object对象,并且最少包含标签名 (tag)、属性 (attrs) 和子元素对象 (children) 三个属性。以对象嵌套的方式来表示 dom树,那么每次 dom 的更改就变成了 js 对象的属性的更改,这样一来就能查找 js 对象的属性变化要比查询 dom 树的性能开销小。

06 删除数组delete和Vue.delete的区别

delete:只是被删除数组成员变为 empty / undefined,其他元素键值不变。

Vue.delete:直接删了数组成员,并改变了数组的键值(对象是响应式的,确保删除能触发更新视图,这个方法主要用于避开 Vue 不能检测到属性被删除的限制)。

07 watch和computed的区别

通俗来讲,既能用 computed 实现又可以用 watch 监听来实现的功能,推荐用 computed。

区别在于computed 的缓存功能,computed 计算属性是用来声明式的描述一个值依赖了其它的值,当所依赖的值或者变量改变时,计算属性也会跟着改变。

watch 监听的是已经在 data 中定义的变量,当该变量变化时,会触发 watch 中的方法。

运用场景:

当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用computed 的缓存特性,避免每次获取值时,都要重新计算。

当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

08 MVVM的理解

MVVM 是 Model-View-ViewModel 的缩写。主要目的是分离视图(View)和模型(Model)。

Model:代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。

View:代表UI 组件,它负责将数据模型转化成UI 展现出来。

ViewModel:监听数据模型的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。

在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的,因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

特点:

  1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。

  2. 可重用性。可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。

  3. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。

  4. 可测试。界面素来是比较难于测试的,测试可以针对ViewModel来写。

09 的作用

包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。

10 vue中ref的作用

ref 被用来给 DOM 元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的 DOM 元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实例。只要想要在 Vue 中直接操作 DOM 元素,就必须用 ref 属性进行注册。

11 v-if和v-show的区别

v-if 是“真正”的条件渲染,同时它也是惰性的,如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块切换过程会发生销毁和重建;具有更高的切换开销,如果在运行时条件很少改变,则使用 v-if 较好。

v-show不管初始条件是什么,元素总是会被渲染,并且只是简单地基于CSS(display:none) 进行切换;具有更好的初始渲染开销,如果切换非常频繁,则使用 v-show 比较好。

12 vue中data为什么是一个函数

1、每个组件都是 Vue 的实例。

2、组件共享 data 属性,当 data 的值是同一个引用类型的值时,改变其中一个会影响其他。

3、组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份 data,就会造成全局数据的污染,导致一个变了全都变。

13 vue全家桶是什么

vue 全家桶包括:vue-router、vuex、vue-resource,再加上构建工具 vue-cli,sass样式和组件库,就是一个完整的 vue 项目的核心构成。

概括起来就是:项目构建工具 + 路由 + 状态管理 + http 请求工具 + 样式管理/组件库。

14 vue中经常使用的修饰符

.stop:阻止事件继续传播(阻止冒泡)

.prevent:阻止默认事件(例如 a 标签的跳转 )

.capture:事件默认是由里往外冒泡,capture 的作用就是反过来,由外向内捕获

.self:只有点击事件绑定的本身才可以触发事件

.once:点击事件只会触发一次;

.passive:当我们在监听元素滚动事件的时候,会一直触发 onscroll 事件,这在 pc 端没有问题,但是在移动端,会让网页变卡,使用这个修饰符,相当于给 onscroll 事件整了一个;

lazy 修饰符;

.sync:父子组件传值,子组件想更新父组件传过来的这个值,使用此修饰符。.sync 为

编译时的语法糖,它会被扩展为一个 v-on 监听器。

15 父子组件嵌套时生命周期钩子函数的执行顺序

加载渲染过程:

父 beforeCreate ->父 created ->父 beforeMount ->子 beforeCreate ->子 created ->子beforeMount ->子 mounted ->父 mounted

子组件更新过程:

父 beforeUpdate ->子 beforeUpdate->子 updated->父 updated

父组件更新过程:

父 beforeUpdate ->父 updated

销毁过程:

父 beforeDestroy ->子 beforeDestroy ->子 destroyed ->父 destroyed

16 组件name的作用

1、允许组件模板(DOM)递归地调用自身。注意,组件在全局用 Vue.component() 注册时,全局 ID 自动作为组件的 name。

2、指定 name 选项的另一个好处是便于调试。有名字的组件有更友好的警告信息。当在有 vue-devtools,未命名组件将显示成 ,这很没有语义。通过提供 name 选项,可以获得更有语义信息的组件树。

3、项目中使用 keep-alive,keep-alive 可允许组件有条件地缓存,但需要搭配组件的 name 选项进行缓存过滤。

17 组件间的通信数据传递

组件关系可分为父-子组件通信、不同独立组件间通信。

1、父组件向子组件:

在父组件使用子组件的标签上进行属性绑定(传数据),子组件通过 props 属性来接收值,还可以设置默认值及指定数据类型。

2、子组件向父组件:

子组件用 this. e m i t ( ) 来触发事件,父组件用 emit()来触发事件,父组件用 emit()来触发事件,父组件用on()来监昕子组件的事件。父组件可以直接在子组件的自定义标签上使用 v-on 来监昕子组件触发的自定义事件。

3、不同独立组件间通信:

通过实例一个 vue 实例 Bus 作为媒介,要相互通信的兄弟组件之中都引入 Bus,之后通过分别调用 Bus 事件触发和监听来实现组件之间的通信和参数传递。

4、多个不同独立组件间通信:建议使用 vuex、pinia(十分推荐)。

18 如何捕获vue组件的错误信息

1、借助 errorCaptured 生命周期钩子函数(2.5.0 版本新增),当捕获一个来自子孙组件的错误时被调用,接收 错误对象、发生错误的组件实例、错误详情 三个参数,return false 后可以阻止错误继续向上抛出。

2、借助 errorHandler 全局钩子,使用 Vue.config.errorHandler 配置,可在 main.js或自定义配置文件中配置,接收参数与 errorCaptured 一致,2.6 版本后可捕捉 v-on 与promise 链的错误,可用于统一错误处理与错误兜底。

Vue.config.errorHandler = function (err, vm, info) {
// handle error
}
从 2.2.0 起,这个钩子也会捕获组件生命周期钩子里的错误。同样的,当这个钩子是 undefined 时,被捕获的错误会通过 console.error 输出而避免应用崩溃从 2.4.0 起,这个钩子也会捕获 Vue 自定义事件处理函数内部的错误了从 2.6.0 起,这个钩子也会捕获 v-on DOM 监听器内部抛出的错误。另外,如果任何被覆盖的钩子或处理函数返回一个 Promise 链 (例如 async 函数),则来自其Promise 链的错误也会被处理。

3、调用接口请求数据时可使用.then()和.catch()方法或者 try … catch()方法

19 v-for循环时key的作用

key 的作用:主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

有相同父元素的子元素必须有独特的(唯一辨识的)key。重复的 key 会造成渲染错误,所以,使用 index 下标进行 key 的绑定是错误的。

20 v-if和v-for可以同时使用吗

vue 官网明确指出:不推荐同时使用 v-for 和 v-if。

原因:v-for 和 v-if 一起使用时,v-for 的优先级比 v-if 更高,也就意味着 v-if 会重复运行与每个 v-for 循环中,影响渲染性能

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值