前言
面試題在網絡上有如海洋之深,對于同一知識點,每個人的理解也各有千秋。我們在面試中常常會遇到一個瞬息間腦海里一片空白的情況,其實這并不是因為我們不懂,而是因為我們在回答的時候缺乏一個清晰的思路。那么問題來了,我們如何能逐步喚醒自己的記憶,娓娓道來呢?
其他前端面試題精選
# 《如何在面試中娓娓道來》前端篇
方法展開
本篇從十個vue面試題案例逐步分解回答步驟,簡單概括即為從一句簡概的描述出發,將一個問題往自己擅長的部分引導。
比如vue面試題常常就會被問到3版本與2版本的比較。其實我們在準備過程中總會遇到這種多種特性描述一個問題的情況,引導式先將自己擅長的部分提出,后加展開描述,其實剩下的就是我們相對記憶薄弱的區塊,就像答題我們先將會的答完,再挖掘自己需要“爭取”的另一部分,這樣既保證一部分得分,又不會因為沒有章法而慌張。
Vue3
題目匯總
- 請解釋Vue3中的Composition API是什么以及它的用途?
- Vue3中的reactive和ref有什么區別?
- 如何在Vue3中實現雙向綁定?
- Vue3的Proxy是如何工作的?
- 請解釋Vue3中的Teleport特性及其用途?
- 如何在Vue3中使用Suspense組件?
- Vue3中的script setup語法是什么?
- 如何在Vue3中使用provide和inject?
- vue3和vue2相比,有什么優化?
- 如何在Vue3中使用自定義指令?
解答篇
1. 請解釋Vue3中的Composition API是什么以及它的用途?
引導式回答:
關鍵詞:組合式API,區別于vue2的選項式API。
展開式回答:
Composition API是一種新的代碼組織方式。
它是一個可選的、高級的、基于函數的API,可以讓你更自由地組織和復用代碼。與vue2的選項式api相比,Composition API允許你按照邏輯關系組織代碼,你可以把相關的數據和方法組織在一起,形成一個可復用的邏輯單元,方便后期提取hooks。
這大大提高了代碼的可讀性和可維護性。(其實也算一種js寫法的回歸)
2. Vue3中的reactive和ref有什么區別?
引導式回答:
reactive
和ref
都是用來創建響應式數據的。
展開式回答:
最主要的區別在于:
reactive
是用來創建響應式對象的。你可以使用reactive
來包裝一個普通的JavaScript對象,然后返回一個響應式的代理版本。這個代理會追蹤其依賴,并在其依賴變更時進行更新。
const state = reactive({ count: 0 })
ref
是用來創建一個響應式的值的。它返回一個具有.value
屬性的對象,這個對象的.value
屬性是響應式的。你可以將ref
用于單個值,如字符串或數字。
const count = ref(0)
reactive
處理的是對象,你可以直接訪問和修改對象的屬性,無需使用.value
。ref
處理的是單個值,訪問或修改值時,需要通過.value
屬性。
3. 如何在Vue3中實現雙向綁定?
引導式回答:
依賴于
v-model
指令。
展開式回答:
- 非自定義組件使用(普通使用):
<template><input v-model="message" />
</template><script>
import { ref } from 'vue';
export default {setup() {const message = ref('');return { message };},
};
</script>
- 自定義組件使用
在自定義組件上使用 v-model 時,情況會有些不同,組件內部必須通過 emits
選項顯式地觸發 'update:modelValue'
事件來更新父組件的數據。
- 首先,在自定義組件中,你需要接收一個名為
modelValue
的prop。這個prop代表了父組件希望與子組件雙向綁定的值。
props: {modelValue: {type: String, // 或你需要的其他類型default: ''}
}
- 當需要更新這個值時,你需要在自定義組件中觸發一個名為
update:modelValue
的事件,并傳入新的值,如下:
this.$emit('update:modelValue', newValue);
然后你就可以在父組件中使用v-model
指令和你的自定義組件進行雙向綁定了:
<YourComponent v-model="someValue" />
在這個例子中,當YourComponent
觸發update:modelValue
事件時,父組件中的someValue
將會被更新為事件傳入的新值。
4. Vue3的Proxy是如何工作的?
引導式回答:
Vue 會使用 Proxy 來包裝原始數據,返回一個 Proxy 對象。
(首先提proxy對象——>后續描述修改對象的屬性為思路)
展開式回答:
在 Vue3 中,Proxy 對象的作用可以被看作是一種"中間人"。
當你試圖獲取或修改 Proxy 對象的屬性時,這些操作都會被 Proxy “攔截”。
當你嘗試訪問 Proxy 對象的某個屬性時,Proxy 不僅會返回該屬性的值,還會告訴 Vue 的響應式系統:“嘿,有人正在訪問這個屬性。”于是,Vue 就會記下這個操作,將當前的“副作用”(比如渲染函數或計算屬性)添加到這個屬性的依賴列表中。這樣,Vue 就能知道哪些副作用依賴于這個屬性。
當你嘗試修改 Proxy 對象的某個屬性時,Proxy 不僅會改變該屬性的值,還會告訴 Vue 的響應式系統:“嘿,有人剛剛修改了這個屬性。”于是,Vue 就會找到所有依賴于這個屬性的副作用,并重新運行它們,以確保它們使用的是最新的屬性值。
通過這種方式,Proxy 對象幫助 Vue 有效地追蹤和管理響應式數據的變化,從而實現數據和視圖的同步更新。
5. 請解釋Vue3中的Teleport特性及其用途。
引導式回答:
關鍵詞:傳送門。
將子組件模板部分渲染到DOM的其他位置(顧名思義:傳送效果)。
展開式回答:
這個特性在很多場景下都非常有用。
例如,你可能要創建一個模態框(modal),這個模態框要覆蓋整個頁面,而不僅僅是它的父組件。在 Vue 2 中,你可能需要通過全局組件或其他方法來實現這個功能,但這往往會導致代碼的復雜性增加。
而在 Vue 3 中,你可以使用 Teleport 來輕松實現這個功能。
你可以通過 <teleport to="目標元素的選擇器">
來使用 Teleport。
例如:
<teleport to="#modal-container"><div class="modal"><!-- 模態框的內容 --></div>
</teleport>
在這個例子中,<div class="modal">
會被渲染到 id 為 modal-container
的元素內,而不是它的父組件內。
6. 如何在Vue3中使用Suspense組件?
引導式回答:
<Suspense>
是一個內置組件,就好像一個包住禮物的盒子。(盒子的表面是#fallback的內容,其中的禮物是#default正在準備的東西)
展開式回答:
使用 <Suspense>
的基本步驟如下:
- 在你的組件模板中,使用
<Suspense>
包裹起你的異步組件。
<Suspense><template #default><AsyncComponent /></template><template #fallback><div>Loading...</div></template>
</Suspense>
- 在上面的代碼中,
<AsyncComponent />
是你的異步組件,它可能是通過defineAsyncComponent()
或者import()
動態加載的組件。 #default
插槽用于放置異步組件,#fallback
插槽則用于放置備用內容,這個備用內容會在異步組件加載過程中顯示。
7. Vue3中的script setup語法是什么?
引導式回答:
關鍵詞:解析語法糖。用于大幅簡化組件的寫法。
展開式回答:
<script setup>
import { ref } from 'vue';let count = ref(0);
function increment() {count.value++;
}
</script>
在模板中,我們可以直接使用在 <script setup>
中定義的響應式數據和方法,就像它們被定義在 data
或 methods
中一樣。
此外,<script setup>
還可以和 defineProps
和 defineEmits
函數一起使用,用于定義組件的 props
和自定義事件。經過這樣的改寫,整個組件的結構會變得更加清晰。
8. 如何在Vue3中使用provide和inject?
引導式回答:
provide
和inject
是一對用于依賴注入的 API,主要用于實現組件之間的通信。
展開式回答:
假設我們有一個父組件,我們可以在其中提供一個名為 theme
的數據:
<template><div><ChildComponent /></div>
</template><script setup>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';let theme = ref('light');
provide('theme', theme);
</script>
然后,在任何子組件或孫子組件中,我們都可以使用 inject
來接收這個 theme
數據:
<template><div :class="theme">I'm a child component</div>
</template><script setup>
import { inject } from 'vue';let theme = inject('theme');
</script>
注意幾個關鍵點:
- provide 和 inject 主要解決了 Vue 中跨級組件間通信的問題。
- provide 和 inject 都可以接收兩個參數。第一個參數是提供或注入的屬性的名稱,第二個參數可選,表示當無法找到提供的屬性時要使用的默認值。
- 使用 provide 和 inject 的組件并不需要保持直接的父子關系,只要是在一個組件樹內,就可以通過這種方式進行數據傳遞。
- 子組件可以覆蓋沿組件樹向上注入的值,這可能會對你實例樹的其他部分產生影響,因此你需要時刻注意這一點。
- 在 Vue 2.x 中,provide 和 inject 是選項;而在 Vue 3 中,它們成為了兩個函數。
9. vue3和vue2相比,有什么優化?
引導式回答:
更快(速度、體積…) 更簡單(setup…) 更強(新特性:傳送門、Suspense…)
展開式回答:
- 性能提升:Vue 3 在性能方面做了大量優化。它的渲染速度比 Vue 2 快約 1.5~2 倍,而且打包尺寸減少了約 41%。
- Composition API:這是 Vue 3 的一個主要特性,它提供了一種更靈活的方式來組織和管理組件的邏輯。這使得在大型項目中管理復雜狀態變得更加容易。
- 更好的 TypeScript 支持:Vue 3 從一開始就用 TypeScript 重寫,因此它提供了更好的 TypeScript 支持。
- Fragments:在 Vue 2 中,每個組件必須有一個根元素。但在 Vue 3 中,這個限制被取消了。你可以在一個組件中返回多個根節點,這幾乎消除了所有需要額外 DOM 元素的需求。
- 更好的自定義指令 API:在 Vue 3 中,自定義指令的 API 更加一致和強大。
- Suspense 組件:Vue 3 介紹了 Suspense 組件,用于在組件等待異步操作完成時提供回退內容。
- 實驗性的
<script setup>
語法:Vue 3.2 引入了<script setup>
語法,它提供了一種更緊湊的方式來編寫單文件組件。 - 其他新特性包括:對于 Portal 的原生支持,更強大的計算屬性,多個 v-model 支持,以及更好的安全性。
10. 如何在Vue3中使用自定義指令?
引導式回答:
關鍵詞:directive
展開式回答:
我們來創建一個自定義指令叫 v-focus,當頁面加載完畢后,此指令可以使一個輸入框自動獲取焦點。
先定義自定義指令:
import { createApp } from "vue";const app = createApp({});app.directive("focus", {// 當被綁定的元素掛載到 DOM 上時mounted(el) {// 獲取焦點el.focus();}
});
然后在模板中使用自定義指令:
<template><input v-focus />
</template>
自定義指令對象可以接受一些函數作為參數:
beforeMount
:與 Vue 2 中的bind
鉤子相對應,一旦指令被綁定到元素上,就會立即調用這個函數,而不必等到節點插入到 DOM 中。mounted
:與 Vue 2 中的inserted
鉤子相對應,一旦綁定的元素插入到父節點中,這個函數就會被調用。beforeUpdate
:在元素更新之前觸發。updated
:在元素更新之后觸發。beforeUnmount
:在指令從元素上卸載前觸發。unmounted
:在指令從元素上卸載后觸發。
這些函數可以接受三個參數:el
,binding
和 vnode
,分別代表指令綁定的元素,綁定對象以及虛擬節點。