最新Vue 3 常见面试题汇总_vue3面试题(1),不了解这些多线程的基础知识很难学懂前端

总结

为了帮助大家更好温习重点知识、更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

内容包括html,css,JavaScript,ES6,计算机网络,浏览器,工程化,模块化,Node.js,框架,数据结构,性能优化,项目等等。

包含了腾讯、字节跳动、小米、阿里、滴滴、美团、58、拼多多、360、新浪、搜狐等一线互联网公司面试被问到的题目,涵盖了初中级前端技术点。

前端面试题汇总

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

JavaScript

性能

linux

    return "$" + value
  },
},

}

* 移除了 .native .sync 修饰符
* 移除了 $listeners
* 移除了 EventBus 的相关属性:$on、$off 和 $once,可以使用第三方库代替,比如 [mitt](https://bbs.csdn.net/topics/618166371)
* 移除了 $children,可以使用 ref 代替
* ...


## 为什么 Vue 3.x 采用了 Proxy 抛弃了 Object.defineProperty() ?


* Proxy 可以代理任何对象,包括数组,而 Vue 2 中是通过重写数组的以下七种方法实现的。


	+ `push()`(将一个或多个元素添加到数组的末尾,并返回该数组的新长度)
	+ `pop()`(移除并返回数组的最后一个元素)
	+ `unshift()`(将一个或多个元素添加到数组的开头,并返回该数组的新长度)
	+ `shift()`(移除并返回数组的第一个元素)
	+ `splice()`(删除数组中的一个或多个元素,并将其返回)
	+ `sort()`(对数组进行排序)
	+ `reverse()`(对数组进行反转)
* Proxy 可以直接监听整个对象而非属性,而 `Object.defineProperty()` 只能先遍历对象属性再去进行监听。相比之下 Proxy 更加简洁,更加高效,更加安全。
* Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的。

 

const cat = {
name: “Tom”,
}

const myCat = new Proxy(cat, {
get(target, property) {
console.log(我的 ${property} 被读取了)
return property in target ? target[property] : undefined
},
set(target, property, value) {
console.log(我的 ${property} 被设置成了 ${value})
target[property] = value
return true
},
})

myCat.name // expected output: 我被读取了:name
myCat.name = “Kitty” // expected output: 我的 name 被设置成了 Kitty

* `Object.defineProperty()` 的本质是在一个对象上定义一个新属性,或者修改一个现有属性。

 

const cat = {
name: “Tom”,
}

Object.defineProperty(cat, “name”, {
get() {
console.log(我被读取了)
},
set(value) {
console.log(我被设置成了 ${value})
},
})

cat.name // expected output: 我被读取了
cat.name = “Kitty” // expected output: 我被设置成了 Kitty

* 而 Proxy 天生用于代理一个对象,它有 13 种基本操作的拦截方法,是 `Object.defineProperty()` 不具备的。


	+ `apply()`(拦截函数的调用)
	+ `construct()`(拦截构造函数的调用)
	+ `defineProperty()`(拦截属性的定义)
	+ `deleteProperty()`(拦截属性的删除)
	+ `get()`(拦截对象属性的读取)
	+ `getOwnPropertyDescriptor()`(拦截对象属性的描述)
	+ `getPrototypeOf()`(拦截对象的原型)
	+ `has()`(拦截对象属性的检查)
	+ `isExtensible()`(拦截对象是否可扩展的检查)
	+ `ownKeys()`(拦截对象的属性列表)
	+ `preventExtensions()`(拦截对象是否可扩展的设置)
	+ `set()`(拦截对象属性的设置)
	+ `setPrototypeOf()`(拦截对象的原型的设置)


## Vue 是如何实现数据双向绑定的?v-model 的原理?


Vue 组件可以通过使用 `v-model` 指令以实现双向绑定。`v-model` 是 vue 的一个语法糖,它用于监听数据的改变并将数据更新。以 input 元素为例:




其实就等价于



<input :value=“searchText” @input=“searchText = $event.target.value” />


## 如何在组件中实现 v-model ?


在 Vue 2 组件中实现 `v-model`,只需定义 `model` 属性即可。



export default {
model: {
prop: “value”, // 属性
event: “input”, // 事件
},
}


在 Vue 3 组合式 API 实现 `v-model`,需要定义 `modelValue` 参数,和 `emits` 方法。



defineProps({
modelValue: { type: String, default: “” },
})

const emits = defineEmits([“update:modelValue”])

function onInput(val) {
emits(“update:modelValue”, val)
}


## 当数据改变时,Vue 是如何更新 DOM 的?(Diff 算法和虚拟 DOM)


当我们修改了某个数据时,如果直接重新渲染到真实 DOM,开销是很大的。Vue 为了减少开销和提高性能采用了 Diff 算法。当数据发生改变时,**Observer** 会通知所有 **Watcher**,**Watcher** 就会调用 `patch()` 方法(Diff 的具体实现),把变化的内容更新到真实的 DOM,俗称**打补丁**。


Diff 算法会对新旧节点进行同层级比较,当两个新旧节点是相同节点的时候,再去比较他们的子节点(如果是文本则直接更新文本内容),逐层比较然后找到最小差异部分,进行 DOM 更新。如果不是相同节点,则删除之前的内容,重新渲染。



![逐层比较](https://img-blog.csdnimg.cn/img_convert/631ec6c42bf13f4b3d9e8b26610b988e.webp?x-oss-process=image/format,png)


`patch()` 方法先根据真实 DOM 生成一颗虚拟 DOM,保存到变量 `oldVnode`,当某个数据改变后会生成一个新的 `Vnode`,然后 `Vnode` 和 `oldVnode` 进行对比,发现有不一样的地方就直接修改在真实 DOM 上,最后再返回新节点作为下次更新的 `oldVnode`。


## 什么是虚拟 DOM?有什么用?


虚拟 DOM(Virtual DOM)就是将真实 DOM 的主要数据抽取出来,并以对象的形式表达,用于优化 DOM 操作。虚拟 DOM 的主要目的是提高性能和减少实际 DOM 操作的次数,从而改善用户界面的渲染速度和响应性。


比如真实 DOM 如下:



123


对应的虚拟 DOM 就是(伪代码):



const vnode = {
type: “div”,
props: {
id: “hello”,
},
children: [
{
type: “h1”,
innerText: “123”,
},
],
}


## Vue 中的 key 有什么用?


* 在 Vue 中,key 被用来作为 VNode 的唯一标识。
* key 主要用在虚拟 DOM Diff 算法,在新旧节点对比时作为识别 VNode 的一个线索。如果新旧节点中提供了 key,能更快速地进行比较及复用。反之,Vue 会尽可能复用相同类型元素。

 
  • {{ item.name }}
* 手动改变 key 值,可以强制 DOM 进行重新渲染。

 
{{ text }}


## watch 和 computed 分别是做什么的?有何区别?


watch 和 computed 都可以用于监听数据,区别是使用场景不同,watch 用于监听一个数据,当数据改变时,可以执行传入的回调函数:




computed 用于返回一个新的数据,在 Vue 3.x 中会返回一个只读的响应式 ref 对象。但是可以接受一个带有 get 和 set 函数的对象来创建一个可写的 ref 对象。




有些人会提到 computed 支持缓存,不支持异步,也是和 watch 的区别。


但这里要告诉大家的是,computed 本身的设计就是为了计算,而非异步的获取一个数据,详情请参考[官网](https://bbs.csdn.net/topics/618166371)。


至于缓存,这同样属于 computed 的特性,它支持缓存,这是和调用普通函数的区别,而不应该和 watch 进行比较,watch 本身用于监听数据变化,在根本上不存在缓存的概念。


## Vue 3 对 diff 算法进行了哪些优化


在 Vue 2 中,每当数据发生变化时,Vue 会创建一个新的虚拟 DOM 树,并对整个虚拟 DOM 树进行递归比较,即使其中大部分内容是静态的,最后再找到不同的节点,然后进行更新。


Vue 3 引入了静态标记的概念,通过静态标记,Vue 3 可以将模板中的静态内容和动态内容区分开来。这样,在更新过程中,Vue 3 只会关注动态部分的比较,而对于静态内容,它将跳过比较的步骤,从而避免了不必要的比较,提高了性能和效率。



foo
bar
{{ dynamic }}

## Vue 实例的生命周期钩子都有哪些?


生命周期钩子是指一个组件实例从创建到卸载(销毁)的全过程,例如,设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。在这个过程中会运行一些叫做生命周期钩子的函数,从而可以使开发者们在不同阶段处理不同的业务。


### Vue 2 和 Vue 3 选项式 API 的钩子大致是一样的,有以下钩子:


* beforeCreate

 实例初始化之前,`$el` 和 `data` 都为 `undefined`。
* created

 实例创建完成,`data` 已经绑定。但 `$el` 不可用。
* beforeMount

 将 `<template>` 和 `data` 生成虚拟 `DOM` 节点,可以访问到 `$el`,但还没有渲染到 `html` 上。
* mounted

 实例挂载完成,渲染到 `html` 页面中。
* beforeUpdate

 `data` 更新之前,虚拟 `DOM` 重新渲染之前。
* updated

 由于 `data` 更新导致的虚拟 `DOM` 重新渲染之后。
* beforeDestroy(Vue 2) | beforeUnmount(Vue 3)

 实例销毁之前(实例仍然可用)。
* destroyed(Vue 2) | beforeUnmount(Vue 3)

 实例销毁之后。所有的事件监听器会被移除,所有的子实例也会被销毁,但 `DOM` 节点依旧存在。该钩子在服务器端渲染期间不被调用。
* activated

 `keep-alive` 专用,实例被激活时调用。
* deactivated

 `keep-alive` 专用,实例被移除时调用。
* errorCaptured

 在捕获了后代组件传递的错误时调用。


### 第一次页面加载会触发这四个钩子:


* beforeCreate
* created
* beforeMount
* mounted


### Vue 3 组合式 API 有以下钩子:


* onBeforeMount()

 在组件被挂载之前被调用。
* onMounted()

 在组件挂载完成后执行。
* onBeforeUpdate()

 在组件即将因为响应式状态变更而更新其 DOM 树之前调用。
* onUpdated()

 在组件因为响应式状态变更而更新其 DOM 树之后调用。
* onBeforeUnmount()

 在组件实例被卸载之前调用。
* onUnmounted()

 在组件实例被卸载之后调用。相当于 Vue 2 的 `destroyed`。
* onErrorCaptured()

 在捕获了后代组件传递的错误时调用。
* onRenderTracked()

 当组件渲染过程中追踪到响应式依赖时调用。只在开发环境生效。
* onRenderTriggered()

 当响应式依赖的变更触发了组件渲染时调用。只在开发环境生效。
* onActivated()

 `keep-alive` 专用,当组件被插入到 DOM 中时调用。
* onDeactivated()

 `keep-alive` 专用,当组件从 DOM 中被移除时调用。
* onServerPrefetch()

 在组件实例在服务器上被渲染之前调用。只在 SSR 模式下生效。


## nextTick 的使用场景和原理


### 使用场景


nextTick 是在下次 DOM 更新循环结束之后执行的一个方法。一般在修改数据之后使用这个方法操作更新后的 DOM。



export default {
data() {
return {
message: “Hello Vue!”,
}
},
methods: {
example() {
// 修改数据
this.message = “changed”
// DOM 尚未更新
this.$nextTick(() => {
// DOM 现在更新了
console.log(“DOM 现在更新了”)
})
},
},
}


### 原理


在 Vue2 当中,nextTick 可以理解为就是收集异步任务到队列当中并且开启异步任务去执行它们。它可以同时收集组件渲染的任务,以及用户手动放入的任务。组件渲染的任务是由 watcher 的 update 触发,并且将回调函数包装为异步任务,最后推到 nextTick 的队列里,等待执行。


而在 Vue3 当中,nextTick 则是利用 promise 的链式调用,将用户放入的回调放在更新视图之后的 then 里面调用,用户调用多少次 nextTick,就接着多少个 then。


## 为什么 Vue 组件中的 data 必须是函数?



### ajax
1)ajax请求的原理/ 手写一个ajax请求?
2)readyState?
3)ajax异步与同步的区别?
4)ajax传递中文用什么方法?

![ajax.PNG](https://img-blog.csdnimg.cn/img_convert/43a1894f013565dbf135493ae0e63d62.webp?x-oss-process=image/format,png)

![前12.PNG](https://img-blog.csdnimg.cn/img_convert/1ef299637eec033de49691e619024c91.webp?x-oss-process=image/format,png)

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**

入的任务。组件渲染的任务是由 watcher 的 update 触发,并且将回调函数包装为异步任务,最后推到 nextTick 的队列里,等待执行。


而在 Vue3 当中,nextTick 则是利用 promise 的链式调用,将用户放入的回调放在更新视图之后的 then 里面调用,用户调用多少次 nextTick,就接着多少个 then。


## 为什么 Vue 组件中的 data 必须是函数?



### ajax
1)ajax请求的原理/ 手写一个ajax请求?
2)readyState?
3)ajax异步与同步的区别?
4)ajax传递中文用什么方法?

[外链图片转存中...(img-3dlLjev6-1715250386713)]

[外链图片转存中...(img-PGDQ1xUE-1715250386714)]

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值