
「面試專欄」前端面試之vuejs篇
- 🖼?序言
- 🎙?一、vue2.x基礎知識預備
- 📻二、vue2.x基礎知識常見面試題
- 1、請說出vue.cli專案中src目錄每個檔案夾和檔案的用法?
- 2、vue.cli中怎樣使用自定義的組件?有遇到過哪些問題?
- 3、v-show和v-if的區別
- 4、為何v-for中要用key
- 5、描述Vue組件生命周期
- (1)單組件生命周期
- (2)父子組件生命周期關系
- 6、Vue組件如何通訊(常見)
- 7、描述組件渲染和更新的程序
- 8、vue如何處理重繪資料不丟失
- 9、雙向資料系結 v-model 的實作原理
- 10、computed 有何特點
- 11、為何組件data必須是一個函式
- 12、ajax請求應該放在哪個生命周期
- 13、如何將組件所有props傳遞給子組件?
- 14、如何自己實作v-model
- 15、多個組件有相同的邏輯,如何抽離?
- 16、何時要使用異步組件
- 17、何時使用keep-alive
- 18、何時需要使用beforeDestory
- 19、什么是作用域插槽
- 20、vuex中action和mutation有何區別
- 21、vue-router常用的路由模式
- 22、如何配置vue-router異步加載
- 23、scope是怎么實作的
- 24、vue常用性能優化方式
- 📟三、vue2.x原理知識預備
- 📠四、vue原理知識常見面試題
- 1、對MVVM的理解
- 2、監聽data變化的核心 API 是什么
- 3、vue如何監聽陣列變化
- 4、請描述回應式原理
- 5、請用vnode描述一個DOM結構
- 6、diff演算法的時間復雜度
- 7、簡述diff演算法程序
- 8、vue模板編譯的原理是什么
- 9、vue為何是異步渲染,$nextTick有何用?
- 10、SPA單頁面應用是什么?
- 11、hash和history的區別是什么?
- (1)hash
- (2)history
- 12、hash和history兩者的選擇
- 🖨?五、vue3.x知識預備
- ??六、vue3.x常見面試題
- 1、vue3和vue2有什么優勢?
- 2、描述vue3生命周期
- 3、如何看待Composition API和Options API
- 4、如何理解ref、toRef和toRefs
- (1)ref是什么
- (2)toRef是什么
- (3)toRefs是什么
- 5、vue3升級了哪些重要的功能?
- 6、Composition API如何實作代碼的邏輯復用?
- 7、Vue3如何實作回應式?
- 8、Watch和watchEffect的區別是什么?
- 9、setup中如何獲取組件實體?
- 10、vue3為何比vue2快?
- 11、vite是什么?
- 12、Composition API和React hooks的對比
- 📸七、結束語
- 🐣彩蛋 One More Thing
- 🏷?往期推薦
- 🏷?番外篇
🖼?序言
對于前端來說, vuejs 是一大常考點,基本上只要候選人的簡歷上有涉及到 vue 的內容,那么面試官一般都會考察,那么,對于 vue 來說,我們需要從 vue2 到 vue3 來做一個基本的學習,以更好的應對面試官的各種刁難問題,
在下面的這篇文章中,將從 vue2 的基礎知識,到 vue2 的原理知識,再到 vue3 的基礎知識和原理知識做一個歸納和總結,同時,周一也將整理出相關的面試題,以供大家可以有一個更好的參考,
下面開始進入本文的講解~
🎙?一、vue2.x基礎知識預備
在了解常見的面試題之前,需要先對 vue 的基礎知識有一個體系的了解,詳細見下圖👇

關于以上內容,已整理成博文,戳下方鏈接進入學習👇
原文:萬字總結vue的基本使用和高級特性,周邊插件vuex和vue-router
鏈接:https://juejin.cn/post/6976040670939054093
📻二、vue2.x基礎知識常見面試題
基于以上知識點,我們將其細分為面試中的常考題,詳細見下圖👇

接下來對這些題進行一一解答,
1、請說出vue.cli專案中src目錄每個檔案夾和檔案的用法?
├── assets 放置靜態資源
├── components 放組件
├── router 定義路由的相關配置
├── views 視圖
├── app.vue 應用主組件
├── main.js 入口檔案
2、vue.cli中怎樣使用自定義的組件?有遇到過哪些問題?
如何使用:
- 在
components目錄新建你的組件檔案(smithButton.vue); - 在需要用的頁面中匯入:
import smithButton from '../components/smithButton.vue'; - 注入到
vue的子組件的components屬性上,components:{smithButton} - 在
template視圖view中使用; - 流程:創建組件→匯入組件→注入組件→使用組件
會遇到的問題:
smithButton 命名,使用的時候需要用 smith-button ,在創建時常用到駝峰命名,但在使用時需把駝峰轉換為 - 表示;
vue 組件解決什么問題?
vue 組件可以提升整個專案的開發效率,能夠頁面抽象成多個相對獨立的模塊,解決了我們傳統專案開發效率低、難維護、復用性等等問題,
3、v-show和v-if的區別
v-show通過css中的display來控制顯示和隱藏;v-if組件是真正的渲染和銷毀,而不是顯示和隱藏;- 當頻繁切換顯示狀態時,用
v-show,否則用v-if,
4、為何v-for中要用key
- 必須使用
key,且不能是index和random; - 原因在于,在
vue的diff演算法中,通過對tag和key來判斷是否為相同節點sameNode,如果是相同節點,則會盡可能的復用原有的DOM節點, - 使用
key的好處是:減少渲染次數,提升渲染性能,
5、描述Vue組件生命周期
(1)單組件生命周期
一般來說,組件生命周期的執行順序為:掛載階段 → 更新階段 → 銷毀階段,下面給出常用組件生命周期的決議,
| 生命周期鉤子 | 介紹 |
|---|---|
| beforeCreate | 在實體初始化之后,資料觀測(data observer) 和 event/watcher 事件配置之前被呼叫, |
| created | 頁面還沒有渲染,但是vue的實體已經初始化結束, |
| beforeMount | 在掛載開始之前被呼叫:相關的 render 函式首次被呼叫, |
| mounted | 頁面已經渲染完畢, |
| beforeUpdate | 資料更新時呼叫,發生在虛擬 DOM 重新渲染和打補丁之前,你可以在這個鉤子中進一步地更改狀態,這不會觸發附加的重渲染程序, |
| updated | 由于資料更改導致的虛擬 DOM 重新渲染和打補丁,在這之后會呼叫該鉤子,當這個鉤子被呼叫時,組件 DOM 已經更新,所以你現在可以執行依賴于 DOM 的操作, |
| activated | keep-alive 組件激活時呼叫, |
| deactivated | keep-alive 組件停用時呼叫, |
| beforeDestroy | 實體銷毀之前呼叫,在這一步,實體仍然完全可用,常用場景有: 自定義事件的系結要解除、setTimeout等定時任務需要銷毀、自己系結的window或者document事件需要銷毀, |
| destroyed | Vue 實體銷毀后呼叫,呼叫后,Vue 實體指示的所有東西都會解系結,所有的事件監聽器會被移除,所有的子實體也會被銷毀, |
(2)父子組件生命周期關系
加載渲染程序
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子組件更新程序
父beforeUpdate->子beforeUpdate->子updated->父updated
父組件更新程序
父beforeUpdate->父updated
銷毀程序
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
6、Vue組件如何通訊(常見)
vue 組件常見的通訊方式有以下三種:
- 父子組件
props和this.$emit; - 自定義事件
event.$no、event.$off和event.$emit; vuex,
7、描述組件渲染和更新的程序
關于組件的渲染和更新程序,需要了解以下這張圖,大家可以從 1-6 依次按順序地對下圖的整個程序進行細化和解讀,

8、vue如何處理重繪資料不丟失
- 對
vuex進行配置,將vuex的狀態儲存到localStorage中; - 在頁面加載時讀取
localStorage里的狀態資訊; - 在頁面重繪時將
vuex里的資訊保存到localStorage里; - 在頁面中將
vuex里的資訊使用computed接收,
9、雙向資料系結 v-model 的實作原理
-
input元素的value = this.name; -
系結
input事件this.name = $event.target.value; -
data更新后觸發重新渲染re-render; -
最核心問題:了解
v-model在模板編譯之后,產生的內容是什么,
10、computed 有何特點
-
具有快取功能,當
data不變時不會進行計算; -
有效地提高性能,
11、為何組件data必須是一個函式
-
export看似是一個物件,但是.vue檔案編譯出來后是一個類; -
在每一個地方(
data,method……)等等進行使用就是對class進行實體化; -
我們在實體化的時候執行
data; -
如果這個
data不是函式的話,那每一個組件的實體資料就都一樣了,就共享了; -
因此需要讓它在閉包之中,
12、ajax請求應該放在哪個生命周期
-
mounted表示整個渲染完成,dom也加載完成,因此ajax請求應該放在mounted生命周期中; -
本質上
js是單執行緒的,并且ajax是異步獲取資料,是異步加載的一個機制; -
如果將其放在
mounted之前是沒有用的,這樣做只會讓邏輯更加混亂; -
原因在于,如果在
mounted之前放ajax請求,那么這個時候js還沒有渲染完成,且又因為ajax請求的資料還是異步的,因此即使是在mounted之前也不能加載,也不會有提前加載的效果,
13、如何將組件所有props傳遞給子組件?
-
父組件通過
$props的而方式將自己的屬性傳遞給子組件; -
之后子組件通過
<User v-bind = "$props" />這種方式去接收父組件傳遞過來的引數, -
注: 細節知識點,優先級不高
14、如何自己實作v-model
第一步,我們先定義一個子組件,名字叫 CustomVModel.vue ,具體代碼如下:
<template>
<!-- $emit是子組件往父組件傳遞資料 -->
<input type="text"
:value="text1"
@input="$emit('change1', $event.target.value)"
>
<!--
1. 上面的 input 使用了 :value 來系結資料,而不是使用 v-model
2. 上面的 change1 和 model.event 要對應起來
3. 上面的 text1 與下面props的 text1 屬性對應起來
-->
</template>
<script>
export default {
model: {
prop: 'text1', // 對應下面 props 的 text1
event: 'change1'
},
props: {
text1: String,
default() {
return ''
}
}
}
</script>
第二步,我們在父組件中使用上面的這個子組件:
<template>
<div>
<p>vue 高級特性</p>
<hr>
<!-- 自定義 v-model -->
<p>{{name}}</p>
<CustomVModel v-model="name"/>
</div>
</template>
<script>
import CustomVModel from './CustomVModel'
export default {
components: {
CustomVModel
},
data() {
return {
name: 'Monday'
}
}
}
</script>
通過上面的代碼我們可以發現,通過系結 value 屬性和 input 事件這兩個語法糖,最終實作資料的雙向系結,
此時我們看下瀏覽器的顯示效果,

通過上圖我們自己發現,結果跟實際的 v-model 結果是一樣的,至此,我們就實作了自定義的 v-model ,以此來操作資料的雙向系結,
15、多個組件有相同的邏輯,如何抽離?
-
在
vue2.x中,當多個組件有相同的邏輯時,可以使用mixin來進行邏輯抽離; -
值得注意的是,
mixin存在有以下問題:- 變數來源不明確,不利于閱讀,
- 多個
mixin可能會造成命名沖突, mixin和組件可能出現多對多的關系,復雜度較高,
-
因此,要慎用
mixin,且vue3.x已經出了Composition API,來解決vue2.x中存在的這些問題,
16、何時要使用異步組件
-
當加載大組件時,需要用到異步組件;
-
當
vue-router路由要進行異步加載時,需要用到異步組件; -
異步組件可以達到優化性能的效果,
17、何時使用keep-alive
-
keep-alive可以快取組件,使得組件不需要重復渲染; -
比如像多個靜態
tab頁的切換; -
keep-alive可以達到優化性能的效果,
18、何時需要使用beforeDestory
-
當解綁自定義事件
event.$off時,需使用beforeDestory來對事件進行銷毀操作; -
當使用定時器系結時間時,在定時器操作結束時,需要清除定時器;
-
解綁自定義的
DOM事件,如window scroll等,需要在beforeDestory生命周期來對其進行事件解綁,
注意: 如果以上三者不做的話,很容易造成記憶體泄漏,
19、什么是作用域插槽
- 父組件模板的所有東西只會在父級作用域內編譯;
- 子組件模板的所有東西只會在子集作用域內編譯;
- 而作用域插槽想解決的問題就是,讓父組件可以訪問到子組件的資料,
20、vuex中action和mutation有何區別
-
action中可以處理異步,mutation不可以; -
mutation做原子操作,即做一個操作,比較原子的; -
action可以整合多個mutation,可以理解為整理多個原子操作的集合,
21、vue-router常用的路由模式
-
hash默認 -
H5 history(需要服務端支持)
已將路由模式整理成博客,具體戳下方鏈接👇
原文:淺談前端路由原理
鏈接:https://juejin.cn/post/6993840419041706014
22、如何配置vue-router異步加載
- 在
vue-router中,使用import來實作異步加載,
23、scope是怎么實作的
(1)scoped的實作原理:
- 給
DOM節點加一個不重復的屬性data-v-5db9451a來標志唯一性, - 如果組件內部還有組件,只會給最外層的組件里的標簽加上唯一屬性欄位,不影響組件內部參考的組件,
(2)vue中scoped的作用:
- 實作組件的私有化,當前
style樣式屬性只屬于當前模塊,不污染全域, - 但是當我們使用公共組件的時候會造成很多困難,
(3)謹慎使用:
- 父組件無
scoped屬性,子組件帶有scoped,父組件是無法操作子組件的, - 父組件有
scoped屬性,子組件無scoped,父組件也無法設定子組件樣式,因為父組件的所有標簽都會帶有data-v-5db9451a唯一標志,但子組件不會帶有這個唯一標志屬性, - 父子組件都有,同理也無法設定樣式,更改起來增加代碼量,
24、vue常用性能優化方式
- 合理使用
v-show和v-if - 合理使用
computed v-for時加key,以及避免和v-if同時使用- 自定義事件、
DOM事件及時銷毀 - 合理使用異步組件
- 合理使用
keep-alive data層級不要太深,盡量扁平- 使用
vue-loader在開發環境做模板編譯(預編譯) - 合理使用
keep-alive webpack層面的優化- 使用
SSR
📟三、vue2.x原理知識預備
在了解常見的面試題之前,需要先對 vue2.x 的原理知識有一個體系的了解,詳細見下圖👇

關于以上內容,已整理成博文,戳下方鏈接進入學習👇
原文1:手把手教你剖析vue回應式原理,監聽資料不再迷茫
鏈接1:https://juejin.cn/post/6978278417951096839
原文2:面試中的網紅虛擬DOM,你知多少呢?深入解讀diff演算法
鏈接2:https://juejin.cn/post/6978621084862005285
原文3:模板編譯template的背后,究竟發生了什么事?帶你了解template的紙短情長
鏈接3:https://juejin.cn/post/6978965732633608222
📠四、vue原理知識常見面試題
基于以上知識點,我們將其細分為面試中的常考題,詳細見下圖👇

接下來對這些題目進行一一解答,
1、對MVVM的理解
所謂 MVVM ,即 Model-View-ViewModel ,
View 即 視圖 ,也就是 DOM ,
Model 即 模型 ,可以理解為 Vue 中組件里面的 data ,
那么這兩者之間,就通過 ViewModel 來做關聯,而 ViewModel 可以做的事情有很多,比如說像監聽事件,監聽指令等,當 Model 層的資料發生修改時,就可以通過 ViewModel ,來把資料渲染到 View 視圖層上,反之,當 View 層觸發 DOM 事件時,就可以通過 ViewModel ,從而使得 Model 層實作資料的修改,
這就是 Vue 中的資料驅動視圖,通過修改 Model 層的資料,來驅動到 View 的視圖中來,

2、監聽data變化的核心 API 是什么
- 所謂
vue的回應式,即組件data的資料一旦變化,就會立刻觸發視圖的更新,實作資料驅動視圖的第一步,需要了解實作回應式的一個核心API,即Object.defineProperty, - 通過
Object.defineProperty,我們可以實作對資料進行get和set操作,即獲取資料和修改資料的操作,從而達到對資料進行回應式的監聽,
3、vue如何監聽陣列變化
要想讓 Object.defineProperty() 這個 API 擁有監聽陣列的能力,我們可以這么做,具體代碼如下:
// 觸發更新視圖
function updateView() {
console.log('視圖更新')
}
// 重新定義陣列原型
const oldArrayProperty = Array.prototype
// 創建新物件,原型指向 oldArrayProperty ,再擴展新的方法不會影響原型
const arrProto = Object.create(oldArrayProperty);
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
arrProto[methodName] = function () {
updateView() // 觸發視圖更新
oldArrayProperty[methodName].call(this, ...arguments)
// Array.prototype.push.call(this, ...arguments)
}
})
// 重新定義屬性,監聽起來
function defineReactive(target, key, value) {
// 深度監聽
observer(value)
// 核心 API
Object.defineProperty(target, key, {
get() {
return value
},
set(newValue) {
if (newValue !== value) {
// 深度監聽
observer(newValue)
// 設定新值
// 注意,value 一直在閉包中,此處設定完之后,再 get 時也是會獲取最新的值
value = newValue
// 觸發更新視圖
updateView()
}
}
})
}
// 監聽物件屬性
function observer(target) {
if (typeof target !== 'object' || target === null) {
// 不是物件或陣列
return target
}
// 污染全域的 Array 原型(如果直接定義在這里面,會直接污染全域)
// Array.prototype.push = function () {
// updateView()
// ...
// }
if (Array.isArray(target)) {
target.__proto__ = arrProto
}
// 重新定義各個屬性(for in 也可以遍歷陣列)
for (let key in target) {
defineReactive(target, key, target[key])
}
}
// 準備資料
const data = {
name: 'monday',
age: 20,
info: {
address: '深圳' // 需要深度監聽
},
nums: ['打籃球', '出來玩', '打乒乓球']
}
// 監聽資料
observer(data)
// 測驗
data.info.address = '上海' // 深度監聽
data.nums.push('神游') // 監聽陣列
復制代碼
此時瀏覽器的列印效果如下:

我們可以看到,兩個資料對應的視圖都更新了,通過對陣列原型的重新定義,我們就讓 Object.defineProperty() 實作了監聽陣列的能力,
4、請描述回應式原理

回應式原理概述:
- 任何一個
Vue組件都會生成一個render函式, - 之后
render函式會生成一個vnode, - 同時,在執行
render函式的時候會觸發data里面的getter,觸發后則會生成依賴, - 所謂依賴,就是在
data觸發到哪個變數,就會將哪一個變數觀察起來, - 之后,需要查看觸發到的這個變數是否是之前作為依賴被觀察起來的,如果是,則觸發
setter進行資料修改;如果不是,則直接進行監聽操作; - 最后,如果確定是之前作為依賴被重新觀察起來的,那就執行
re-render重新渲染操作,并且進行patch(vnode, newVnode),
5、請用vnode描述一個DOM結構
根據下方的 html 代碼,用 v-node 模擬出該 html 代碼的 DOM 結構,
html代碼:
<div id="div1" class="container">
<p>
vdom
</p>
<ul style="font-size:20px;">
<li>a</li>
</ul>
</div>
復制代碼
用JS模擬出以上代碼的DOM結構:
{
tag: 'div',
props:{
className: 'container',
id: 'div1'
},
children: [
{
tag: 'p',
chindren: 'vdom'
},
{
tag: 'ul',
props:{ style: 'font-size: 20px' },
children: [
{
tag: 'li',
children: 'a'
}
// ....
]
}
]
}
6、diff演算法的時間復雜度
- 樹的時間復雜度是 O(n3) ,因此,我們就想辦法,優化其時間復雜度從O(n3)到O(n),以達到操作
vdom節點,那這個優化程序其實我們所說的diff演算法, - 所以,
diff演算法的時間復雜度為O(n),
7、簡述diff演算法程序
- 首先,對比節點本身,要先判斷是否為同一節點,如果不為相同節點,則洗掉該節點重新創建節點進行替換;
- 如果為相同節點時,進行
patchVnode,判斷如何對該節點的子節點進行處理,先判斷一方有子節點一方沒有子節點的情況(如果新的children沒有子節點,則將舊的子節點移除); - 比較如果都有子節點,則進行
updateChildren,判斷如何對這些新老節點的子節點進行操作(diff核心), - 匹配時,找到相同的子節點,遞回比較子節點,
注意: 在 diff 中,只對同層的子節點進行比較,放棄跨級的節點比較,使得時間復雜從 O(n^3) 降低值 O(n) ,也就是說,只有當新舊 children 都為多個子節點時才需要用核心的 diff 演算法進行同層級比較,
8、vue模板編譯的原理是什么
vue在進行模板編譯之后,會先轉化成一個render函式,之后繼續執行render函式,執行完成之后回傳一個vnode;- 在得到
vnode之后,基于vnode的基礎上,再執行patch和diff,
9、vue為何是異步渲染,$nextTick有何用?
vue是組件級更新,一旦當前組件里的資料變了,那么它就會去更新這個組件,- 但是試想一下,如果當資料更改一次,組件就要去重新渲染一次,這樣對性能來說都是不太友好的,
- 因此,為了防止資料一更新就更新組件,所以需要異步渲染來處理,
- 而異步渲染的核心的方法就是
nextTick,$nextTick可以在DOM更新完之后,再觸發回呼,
10、SPA單頁面應用是什么?
SPA,即單頁面應用(Single Page Application),所謂單頁 Web 應用,就是只有一張 Web 頁面的應用,單頁應用程式 (SPA) 是加載單個 HTML 頁面并在用戶與應用程式互動時動態更新該頁面的 Web 應用程式,瀏覽器一開始會加載必需的 HTML 、 CSS 和 JavaScript ,所有的操作都在這張頁面上完成,都由 JavaScript 來控制,
現如今,為了配合單頁面 Web 應用快速發展的節奏,各類前端組件化技術堆疊層出不窮,近幾年來,通過不斷的版本迭代, vue 和 react 兩大技術堆疊脫穎而出,成為當下最受歡迎的兩大技術堆疊,
11、hash和history的區別是什么?
(1)hash
- hash變化會觸發網頁跳轉,即瀏覽器的前進和后退,
hash可以改變url,但是不會觸發頁面重新加載(hash的改變是記錄在window.history中),即不會重繪頁面,也就是說,所有頁面的跳轉都是在客戶端進行操作,因此,這并不算是一次http請求,所以這種模式不利于SEO優化,hash只能修改#后面的部分,所以只能跳轉到與當前url同檔案的url,hash通過window.onhashchange的方式,來監聽hash的改變,借此實作無重繪跳轉的功能,hash永遠不會提交到server端(可以理解為只在前端自生自滅),
(2)history
- 新的
url可以是與當前url同源的任意url,也可以是與當前url一樣的地址,但是這樣會導致的一個問題是,會把重復的這一次操作記錄到堆疊當中, - 通過
history.state,添加任意型別的資料到記錄中, - 可以額外設定
title屬性,以便后續使用, - 通過
pushState、replaceState來實作無重繪跳轉的功能, - 使用
history模式時,在對當前的頁面進行重繪時,此時瀏覽器會重新發起請求,如果nginx沒有匹配得到當前的url,就會出現404的頁面, - 而對于
hash模式來說, 它雖然看著是改變了url,但不會被包括在http請求中,所以,它算是被用來指導瀏覽器的動作,并不影響服務器端,因此,改變hash并沒有真正地改變url,所以頁面路徑還是之前的路徑,nginx也就不會攔截, - 因此,在使用
history模式時,需要通過服務端來允許地址可訪問,如果沒有設定,就很容易導致出現404的局面,
12、hash和history兩者的選擇
to B的系統推薦用hash,相對簡單且容易使用,且因為hash對url規范不敏感;to C的系統,可以考慮選擇H5 history,但是需要服務端支持;- 能先用簡單的,就別用復雜的,要考慮成本和收益,
🖨?五、vue3.x知識預備
關于 vue3 模塊,我將把基礎知識和原理的內容結合在一起進行整理,詳細見下圖👇

關于以上內容,已整理成博文,戳下方鏈接進入學習👇
原文1: 一文了解vue3基礎新特性
鏈接1: https://juejin.cn/post/6976400439793172487
原文2: 敲黑板!vue3重點!一文了解Composition API新特性:ref、toRef、toRefs
鏈接2: https://juejin.cn/post/6976679225239535629
原文3: 一文get一波 vue3.x 進階新特性
鏈接3: https://juejin.cn/post/6976040670939054093
原文4: vue2的回應式原理學“廢”了嗎?繼續觀摩vue3回應式原理Proxy
鏈接4: https://juejin.cn/post/6979368550225936392
??六、vue3.x常見面試題
基于以上知識點,我們將其細分為面試中的常考題,詳細見下圖👇

接下來對這些題進行一一解答,
1、vue3和vue2有什么優勢?
vue3比vue2來說,性能上更好,代碼體積更小,并且有更好的ts支持,- 同時,更為突出的特點是,
vue3有更好的代碼組織能力,有更好的邏輯抽離能力,并且還有更多各式各樣的新功能, - 其中尤為突出的就是大家平常耳熟能詳的
Composition API和Options API,
2、描述vue3生命周期
以下給出 Vue2 與 Vue3 生命周期的對比,
| Vue2生命周期(Options API) | Vue3生命周期(Composition API) | 含義 |
|---|---|---|
| beforeCreate | setup | 在實體初始化之后,資料觀測(data observer) 和 event/watcher 事件配置之前被呼叫 |
| created | setup | 頁面還沒有渲染,但是vue的實體已經初始化結束, |
| beforeMount | onBeforeMount | 在掛載開始之前被呼叫:相關的 render 函式首次被呼叫, |
| mounted | onMounted | 頁面已經渲染完畢, |
| beforeUpdate | onBeforeUpdate | 資料更新時呼叫,發生在虛擬 DOM 重新渲染和打補丁之前,你可以在這個鉤子中進一步地更改狀態,這不會觸發附加的重渲染程序, |
| updated | onUpdated | 由于資料更改導致的虛擬 DOM 重新渲染和打補丁,在這之后會呼叫該鉤子,當這個鉤子被呼叫時,組件 DOM 已經更新,所以你現在可以執行依賴于 DOM 的操作, |
| beforeDestory | onBeforeUnmount | 實體銷毀之前呼叫,在這一步,實體仍然完全可用, |
| destroy | onUnmounted | Vue 實體銷毀后呼叫, |
3、如何看待Composition API和Options API
對于 Composition API 和 Options API 的使用,主要有以下幾點建議:
- 兩者不建議共用,不然很容易引起混亂;
- 對于小型專案、或者業務邏輯比較簡單的專案,建議使用
Options API; - 對于中大型專案、或者邏輯比較復雜的專案,建議使用
Composition API,相較于Options API來說,Composition API對大型專案更好一些,邏輯的抽離,代碼的復用,使得大型專案得以更好的維護,
4、如何理解ref、toRef和toRefs
(1)ref是什么
ref是可以生成值型別(即基本資料型別) 的回應式資料;ref可以用于模板和reactive;ref通過.value來修改值(一定要記得加上.value);ref不僅可以用于回應式,還可以用于模板的DOM元素,
(2)toRef是什么
-
toRef可以回應物件Object,其針對的是某一個回應式物件(reactive封裝)的屬性prop, -
toRef和物件Object兩者保持參考關系,即一個改完另外一個也跟著改, -
toRef如果用于普通物件(非回應式物件),產出的結果不具備回應式,如下代碼所示:
//普通物件
const state = {
age: 20,
name: 'monday'
}
//回應式物件
const state = reactive({
age: 20,
name: 'monday'
})
(3)toRefs是什么
- 與
toRef不一樣的是,toRefs是針對整個物件的所有屬性,目標在于將回應式物件(reactive封裝)轉換為普通物件, - 普通物件里的每一個屬性
prop都對應一個ref, toRefs和物件Object兩者保持參考關系,即一個改完另外一個也跟著改,
5、vue3升級了哪些重要的功能?
- createApp
- emits(父子組件間的通信)
- 多事件處理
- Fragment
- 移除
.sync - 異步組件
- 移除filter
- Teleport
- Suspense
6、Composition API如何實作代碼的邏輯復用?
composition API通過把代碼的邏輯抽離出來進行封裝,并把封裝的內容直接參考到生命周期里面,已達到代碼的邏輯復用效果,
7、Vue3如何實作回應式?
- 利用
reactive注冊回應式物件,對函式回傳值進行操作, - 利用
Proxy劫持資料的get,set,deleteProperty,has,own, - 利用
WeakMap,Map,Set來實作依賴收集, - 缺點: 使用大量
ES6新增特性,舊版本瀏覽器兼容性差,
8、Watch和watchEffect的區別是什么?
- 兩者都可以監聽
data屬性變化; watch需要明確監聽哪個屬性;- 而
watchEffect會根據其中的屬性,自動監聽其變化,
9、setup中如何獲取組件實體?
在 vue2 中, Options API 可以使用 this 來獲取組件的實體,但是到現在的 vue3 ,已經被摒棄掉了,在 setup 和其他 Composition API 中沒有 this ,但是它提供了一個 getCurrentInstance 來獲取當前的實體,
10、vue3為何比vue2快?
- Proxy回應式
- PatchFlag
- hoistStatic
- cacheHandler
- SSR優化
- tree-shaking
11、vite是什么?
vite是一個前端的打包工具,是vue作者發起的一個專案;vite借助vue的影響力,發展較快,和webpack有著一定的競爭關系;- 優勢:
vite使得程式在開發環境下無需打包,且啟動非常快速,
12、Composition API和React hooks的對比
- 前者
setup只會被呼叫一次,而后者函式會被多次呼叫, - 前者無需
useMemo和useCallback(即快取資料和快取函式),因為setup只呼叫一次, - 前者無需顧慮呼叫順序,而后者需要保證
hooks的順序一致, - 前者
reactive+ref比后者的useState,要難理解,
📸七、結束語
從 vue2.x 的基礎知識,再到 vue2.x 的原理知識,最后到 vue3.x 的新特性和原理知識學習,全文貫穿著 vue 的知識要點及相關知識點所涉及到的一些面試題,
最后,關于這部分內容已整理成 PDF ,獲取方式放在彩蛋里面,有需要的小伙伴自取o!
🐣彩蛋 One More Thing
🏷?往期推薦
vue2.x 和 vue3.x 的原理學習,累計博文輸出 11 篇,以下是相關專欄文章~
- vue.js基礎知識👉基礎知識專欄傳送門
- vue.js原理知識👉原理知識專欄傳送門
面試專欄 pdf 版本:
-
微信搜索
星期一研究室并關注,回復關鍵詞vue面試pdf獲取相關資料~ -
回復
面試大全pdf可獲取全系列資料!
更新地址:
- offer來了面試專欄
🏷?番外篇
- 如果這篇文章對你有用,記得留個腳印jio再走哦~
- 以上就是本文的全部內容!我們下期見!👋👋👋
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/357140.html
標籤:其他
下一篇:顫振中的函式
