Vue前端面试题记录(附答案)

864 阅读9分钟

2022最新前端面试题记录

Vue的理解和认识?

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

Vue2和Vue3生命周期?

Vue2Vue3描述
beforeCreatesetup创建前
createdsetup创建完成
beforeMountonBeforeMount组件挂载之前调用
mountedonMounted组件挂载时调用
beforeUpdateonBeforeUpdate数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
updatedonUpdated由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
beforeDestroyonBeforeUnmount在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
destroyedonUnmounted卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
activatedonActivated缓存的组件激活时调用
deactivatedonDeactivated缓存的组件停用时调用
errorCapturedonErrorCaptured当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

Vue父子组件生命周期顺序?

一、加载渲染过程

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

二、子组件更新过程

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

三、父组件更新过程

父beforeUpdate->父updated

四、销毁过程

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

route和router的区别?

$route 是“路由信息对象”,包括pathparamshashqueryfullPathmatchedname等路由信息参数。而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等。

原型和原型链的理解?

我们知道在es6之前,js没有类和继承的概念,js是通过原型来实现继承的。在js中一个构造函数默认自带有一个prototype属性, 这个的属性值是一个对象,同时这个prototype对象自带有一个constructor属性,这个属性指向这个构造函数,同时每一个实例 都有一个__proto__属性指向这个prototype对象,我们可以将这个叫做隐式原型,我们在使用一个实例的方法的时候,会先检查 这个实例中是否有这个方法,没有则会继续向上查找这个prototype对象是否有这个方法,刚刚我们说到prototype是一个对象, 那么也即是说这个是一个对象的实例,那么这个对象同样也会有一个__proto__属性指向对象的prototype对象。

数据类型,栈内存,堆内存?

栈内存:(存放基本类型:字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol)

  • 存储的值大小固定
  • 空间较小
  • 可以直接操作其保存的变量,运行效率高
  • 由系统自动分配存储空间

堆内存:(存放引用类型:对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date))

  • 存储的值大小不定,可动态调整
  • 空间较大,运行效率低
  • 无法直接操作其内部存储,使用引用地址读取
  • 通过代码进行分配空间

使用new操作符实例化一个对象的具体步骤?

1.构造一个新的对象
2.将构造函数的作用域赋给新对象(也就是说this指向了新的对象)
3.执行构造函数中的代码
4.返回新对象

异步编程方法?

1.callback 回调函数
2.generator + io库
3.promise
4.async  await

call,bind,apply区别及实现?

call调用 将方法中的this指向call中第一个参数,当第一个参数为null、undefined时,默认指向window; call中第一个参数之后是要传递给方法的参数列表。
apply与call相似,不同之处在于传递给方法的参数形式不一致。apply传递给方法的参数是数组的形式。
call和apply在改变方法的this指向时,会同时执行方法;而bind不会执行方法,而是返回改变this指向后的新方法。

a.call(b,1,2,3)  同时执行方法
a.apply(b,[1,2,3])  同时执行方法
a.bind(b)  不会执行方法,返回一个函数

原理实现:

Function.prototype.myCall = function (context, ...arg) {
    const fn = Symbol('临时属性')
    context[fn] = this
    let _val = context[fn](...arg)
    delete context[fn]
    return _val
}
Function.prototype.myApply = function (context, arg) {
    const fn = Symbol('临时属性')
    context[fn] = this
    let _val = context[fn](...arg)
    delete context[fn]
    return _val
}
Function.prototype.myBind = function (objThis, ...params) {
    const thisFn = this; // 存储源函数以及上方的params(函数参数)
    // 对返回的函数 secondParams 二次传参
    let fToBind = function (...secondParams) {
        console.log('secondParams',secondParams,...secondParams)
        const isNew = this instanceof fToBind // this是否是fToBind的实例 也就是返回的fToBind是否通过new调用
        const context = isNew ? this : Object(objThis) // new调用就绑定到this上,否则就绑定到传入的objThis上
        return thisFn.call(context, ...params, ...secondParams); // 用call调用源函数绑定this的指向并传递参数,返回执行结果
    };
    fToBind.prototype = Object.create(thisFn.prototype); // 复制源函数的prototype给fToBind
    return fToBind; // 返回拷贝的函数
};

Set、Map、WeakSet、WeakMap

SetMap 都是强引用,都可以遍历,比如 for of / forEach

WeakSetWeakMap 都是弱引用,对 GC(垃圾回收) 更加友好,都不能遍历

Set 和 WeakSet 只有键值(key)没有键名,Map 和 WeakMap 是键值对的集合

强弱引用:比如: let obj = {} 就默认创建了一个强引用的对象,只有手动将 obj = null,在没有引用的情况下它才会被垃圾回收机制进行回收,如果是弱引用对象,垃圾回收机制会自动帮我们回收,某些情况下性能更有优势,比如用来保存 DOM 节点,不容易造成内存泄漏

Vuex原理?

vuex是利用vue的mixin混入机制,在beforeCreate钩子前混入vuexInit方法,vuexInit方法实现了store注入vue组件实例,并注册了vuex store的引用属性$store
Vuex从使用到原理解析

Promise原理?

Promise原理及实现

双向绑定流程?

结合Vue源码
1.new Vue()首先执行初始化,对data执行响应化处理,这个过程发生在Observe中
2.同时对模板执行编译,找到其中动态绑定的数据,从data中获取并初始化视图,这个过程发生在Compile中
3.同时定义⼀个更新函数和Watcher,将来对应数据变化时Watcher会调用更新函数
4.由于data的某个key在⼀个视图中可能出现多次,所以每个key都需要⼀个管家Dep来管理多个Watcher
5.将来data中数据⼀旦发生变化,会首先找到对应的Dep,通知所有Watcher执行更新函数

computed 和 watch 的区别和运用的场景?

computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;

watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;

运用场景:

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

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

Vue原理解析(九):搞懂computed和watch原理,减少使用场景思考时间

在哪个生命周期内调用异步请求?

可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。但是本人推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面 loading 时间;

  • ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;

vm.$set 的实现原理是?

如果目标是数组,直接使用数组的 splice 方法触发相应式;

如果目标是对象,会先判读属性是否存在、对象是否是响应式,最终如果要对属性进行响应式处理,则是通过调用 defineReactive 方法进行响应式处理( defineReactive 方法就是 Vue 在初始化对象时,给对象属性采用 Object.defineProperty 动态添加 getter 和 setter 的功能所调用的方法)

Vue的修饰符?

事件修饰符

.stop 阻止事件继续传播
.prevent 阻止标签默认行为
.capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
.self 只当在 event.target 是当前元素自身时触发处理函数
.once 事件将只会触发一次
.passive 告诉浏览器你不想阻止事件的默认行为

v-model的修饰符

.lazy 默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步
.number 自动将用户的输入值转化为数值类型
.trim 自动过滤用户输入的首尾空格

VueX之actions与mutations的区别?

actions

1、用于通过提交mutation改变数据
2、会默认将自身封装为一个Promise
3、可以包含任意的异步操作

mutations

1、通过提交commit改变数据
2、只是一个单纯的函数
3、不要使用异步操作,异步操作会导致变量不能追踪

JS继承的实现方式?

原型&原型链&继承

JavaScript常用八种继承方案

箭头函数为什么不能作为构造函数?

箭头函数为什么不能作为构造函数?

Vue为什么采用异步更新?

首先要明确一点:vue是组件级更新,也就是说,每一次的更新都是渲染整个组件,如果是同步的话,一旦修改了data属性,便会触发对应的 watcher,然后调用对应 watcher 下的 update 方法更新视图,那么结果显而易见,太频繁了 !如下代码:

data(){
  a:1,
  b:2,
  c:3
}
//如果是同步的话 修改data中的属性 
//this.a = 2;this.b = 3;this.c = 4;  这样会调用三次update方法渲染视图,很耗性能,用户体验感也不好   

什么是异步更新呢?
异步更新是:Vue会在本轮数据更新后,再去异步更新视图!

Vue如何实现异步更新?

graph TB

执行1["dep.notify()通知watcher进行更新操作"]
-->
执行2["依次调用watcher的update方法subs[i].update"]
-->
执行3["将watcher去重后放入队列中queueWatcher"]
-->
执行4["异步清空watcher队列nextTick(flushSchedulerQueue)"]

手写 Vue2 系列 之 异步更新队列

Vue初始化的时候都做了什么

Vue源码解析(一):Vue 初始化时到底做了什么事情

深入理解TCP、UDP协议及两者的区别

blog.csdn.net/striveb/art…

怎样理解事件循环,哪些是宏任务,哪些是微任务

微任务包括 process.nextTick ,promise ,Object.observe ,MutationObserver
宏任务包括 script , setTimeout ,setInterval ,setImmediate ,I/O ,UI rendering
浏览器和Node 环境下,microtask 任务队列的执行时机不同

  • Node端,microtask 在事件循环的各个阶段之间执行
  • 浏览器端,microtask 在事件循环的 macrotask 执行完之后执行

事件循环宏任务和微任务

Vue 项目优化

1.代码层面的优化

v-if 和 v-show 区分使用场景

computed 和 watch 区分使用场景

v-for 遍历必须为 item 添加 key,且避免同时使用 v-if

长列表性能优化

事件的销毁

图片资源懒加载

路由懒加载

第三方插件的按需引入

优化无限列表性能

服务端渲染 SSR or 预渲染

2.Webpack 层面的优化

Webpack 对图片进行压缩

减少 ES6 转为 ES5 的冗余代码

提取公共代码

模板预编译

提取组件的 CSS

优化 SourceMap

构建结果输出分析

Vue 项目的编译优化

3.基础的 Web 技术的优化

开启 gzip 压缩

浏览器缓存

CDN 的使用

使用 Chrome Performance 查找性能瓶颈

Webpack优化?

每个前端都必须要学会的Webpack优化手段

现在要你实现一个埋点监控SDK,你会怎么设计?

主要由以下三个点出发 SDK的设计:

  • 新建实例时需要传入一个id,因为这个埋点监控系统往往是给多个业务去使用的,通过id去区分不同的数据来源。

埋点监控的职能范围:

  • 用户行为监控
  • 页面性能监控
  • 错误报警监控
    • Js原生报错
    • Vue、React组件报错

数据的发送:

  • 借助img标签的的src属性发送数据给服务器

现在要你实现一个埋点监控SDK,你会怎么设计?