1.Vue3與 Vue2的核心區別有哪些?
-
?
響應式系統
?:- ? Vue2:通過Object.defineProperty 實現響應式。這種方式在處理對象屬性的添加和刪除時存在局限性,且無法直接監控數組的變化 ?;
- ?Vue3:采用Proxy 實現響應式,可以直接監控數組的變化,且性能更高。Proxy 提供了更多的功能,如攔截、應用、擁有密鑰等,這些在 Object.defineProperty 中無法實現 ?;
-
?
性能優化
?:- ?Vue3在性能上有顯著提升,包括打包大小減少41%,初次渲染速度提升55%,更新渲染速度提升133%,內存占用減少54%?;
- ? 虛擬DOM優化 ?:Vue3重構了虛擬DOM的實現,優化了模板編譯時間,提取和重用了內聯事件,減少了不必要的重繪和重新計算 ?;
-
?
組合式 API?
:- ?Vue2采用選項式 API(Options API),邏輯分散在 data、props、computed、watch 等選項中,導致代碼可讀性差 ?;
- ?Vue3引入了組合式 API(Composition API),將相關邏輯放在一個函數中,增強了代碼的可讀性和內聚性。通過 setup 函數、ref、reactive、watch 等函數組織代碼,提高了邏輯復用性和代碼維護性 ?;
-
?
生命周期鉤子
?:- ?Vue2有 10 個生命周期鉤子,如 beforeCreate、created、beforeMount、mounted 等 ?;
- ?Vue3簡化了生命周期鉤子,只有 7 個,主要包括 setup、onBeforeMount、onMounted、onBeforeUpdate、onUpdated、onBeforeUnmount、onUnmounted 等 ?;
-
?
對 TypeScript 的支持
?:- ?Vue3原生支持TypeScript,提供了更好的類型推斷和類型安全,減少了手動類型注釋的需求,提升了代碼質量和開發效率 ?;
2.Vue3.0所采用的Composition Api 與Vue2.x使用的Options Api有什么不同?
Options API
:邏輯分散在 data/methods/computed 等選項中,復用需 Mixin;
Composition API
:通過 setup 函數組合邏輯,復用通過自定義 Hook,代碼更清晰;
區別:
-
代碼組織方式
:- Options API:按功能模塊拆分代碼(data、methods、computed等選項),邏輯分散在不同選項中;
- Composition API:通過setup函數以函數式風格組織代碼,邏輯按功能抽取為獨立函數(如useCounter);
-
邏輯復用機制
:- Options API: 通過mixins復用邏輯,但存在命名沖突、變量來源不清晰等問題;
- Composition API:通過自定義組合函數(如useFetch)實現邏輯復用,變量作用域明確,避免命名污染;
-
類型支持
:- Options API:需通過@types/vue聲明類型,類型推導較弱,復雜場景易出錯;
- Composition API:原生支持TypeScript,函數參數和返回值可明確標注類型,類型推導更精準;
-
響應式系統的使用
:- Options API:通過this訪問響應式數據,依賴Object.defineProperty實現;
- Composition API:通過ref、reactive等函數顯式創建響應式變量,直接操作值(如count.value++)。更細粒度的依賴追蹤(基于Proxy),支持動態新增/刪除屬性;
-
生命周期鉤子
:- Options API:直接使用created、mounted等生命周期選項;
- Composition API:在setup中通過onMounted、onUpdated等函數注冊生命周期鉤子,邏輯更集中;
-
適用場景
:- Options API:簡單組件或對TypeScript需求不高的項目;
- Composition API:復雜組件、大型項目或需要邏輯高度復用的場景;
3.Vue2 和 Vue3 雙向綁定的原理和區別?
Vue2的雙向綁定原理:Vue 2 的雙向綁定是基于 Object.defineProperty 和發布-訂閱模式實現的。以下是其實現的關鍵步驟:
-
數據劫持
:- Vue2 使用Object.defineProperty對數據對象的每個屬性進行劫持,通過定義getter和setter 方法來攔截數據的讀取和修改操作;
- 當數據被訪問時,觸發getter,進行依賴收集;當數據被修改時,觸發setter,通知視圖更新;
-
依賴收集
:- 在組件初始化時,Vue會解析模板中的指令(如 v-model),并為每個依賴于響應式數據的地方創建一個Watcher 實例;
- Watcher 會將自身添加到對應數據屬性的Dep中,Dep用于管理所有依賴該屬性的Watcher;
-
視圖更新
:- 當數據通過setter被修改時,Dep會通知所有相關的 Watcher,Watcher則會調用更新函數來重新渲染視圖;
Vue3的雙向綁定原理:
-
數據劫持
:- Vue3使用Proxy來攔截對象的操作,包括屬性的訪問、修改、刪除等;
- Proxy提供了更全面的攔截能力,能夠直接處理對象的動態屬性添加和刪除;
-
依賴收集與更新
:- 在初始化時,Vue3通過Proxy的getter攔截器進行依賴收集,將Watcher添加到對應的依賴管理器中;
- 當數據通過setter被修改時,Proxy會通知所有相關的Watcher,觸發視圖更新;
區別:
-
底層實現
:- Vue 2:基于Object.defineProperty,只能劫持對象的現有屬性,無法自動檢測新屬性的添加或刪除;
- Vue 3:基于Proxy,能夠攔截對象的所有操作,包括動態屬性的添加和刪除;
-
性能優化
:- Vue 2:由于使用發布-訂閱模式,當數據變化時,所有訂閱者都需要被通知,可能導致性能問題;
- Vue 3:通過Proxy,能夠更精確地檢測數據變化,減少不必要的更新,提高性能;
-
靈活性
:- Vue 2:在處理復雜數據結構時,如動態添加屬性或修改數組長度,需要使用Vue.set 或其他方法;
- Vue 3:直接支持動態屬性和數組操作,無需額外方法;
-
對 TypeScript 的支持
:- Vue 2:類型系統相對較弱;
- Vue 3:提供了更豐富的類型定義和更好的集成,更適合TypeScript開發;
4.Vue3的emits選項定義組件事件與Vue2的emit事件處理有何不同?
-
聲明方式
:強制顯式 vs 隱式觸發- Vue3:必須通過emits選項聲明事件(選項式 API)或 defineEmits(組合式 API),否則觸發未聲明事件時會拋出警告;
- Vue2:無需聲明,直接通過this.$emit觸發事件,未監聽的事件會靜默忽略;
-
類型安全
:原生支持 vs 依賴第三方- Vue3:支持TypeScript類型標注,精確約束事件參數類型;
- Vue2:無原生類型支持,需依賴vue-class-component等庫實現類型約束;
-
錯誤處理
:警告提示 vs 靜默失敗- Vue3:觸發未聲明的事件時,若父組件未監聽,則拋出警告(可通過 inheritAttrs: false禁用);
- Vue2:觸發未聲明事件時,不會報錯,直接忽略;
-
繼承行為
:事件與屬性分離- Vue3:事件不會被繼承到子組件的根元素,避免與HTML原生事件沖突;
- Vue2:事件會被自動繼承到子組件根元素,需通過inheritAttrs: false 關閉;
-
參數驗證
:內置支持 vs 手動實現- Vue3 :emits選項可直接校驗參數;
- Vue2:需在事件觸發時手動添加參數校驗邏輯;
5.簡述Vue 3的插槽和Vue 2有何不同 ?
-
指令統一化
:- Vue 2:使用
slot
屬性定義具名插槽,slot-scope
接收作用域數據; - Vue 3:統一使用
v-slot
指令,語法更簡潔;
- Vue 2:使用
-
作用域插槽簡化
:- Vue 3:作用域數據直接通過
v-slot
的參數接收,支持解構; - Vue 2:需通過
slot-scope
顯式聲明,且作用域鏈較長時易混淆;
- Vue 3:作用域數據直接通過
-
模板限制
:- Vue 3:
v-slot
必須寫在<template>
標簽上(除默認插槽的獨占縮寫); - Vue 2:
slot
和slot-scope
可用于任意 HTML 標簽;
- Vue 3:
-
動態插槽名
:- Vue3:支持動態指定插槽名;
- Vue2:需通過條件渲染間接實現;
-
默認插槽縮寫
:- Vue3:默認插槽可省略
:default
; - Vue2:需顯式聲明
slot="default"
;
- Vue3:默認插槽可省略
-
組合式API集成
:- Vue3:結合
<script setup>
,插槽使用更簡潔,類型推導更友好;
- Vue3:結合
-
Fragments支持
:- Vue3:子組件可返回多個根節點(
<>...</>
),插槽內容可分布在多個節點中; - Vue2:子組件必須有單個根節點,限制了插槽布局靈活性;
- Vue3:子組件可返回多個根節點(
6.Vue3的優勢?
性能優化?
:- 編譯時間減少:Vue3的模板編譯器進行了優化,編譯速度比Vue2快了30%;
- 運行時性能提升:重寫的虛擬DOM和響應性系統使得運行時性能更高效,減少了內存占用和CPU使用率;
- 減少包體積:通過Tree-shaking優化,Vue3的包體積比Vue2小了50%;
組合式API?
:- 模塊化代碼:通過組合式API,可以將邏輯提取到單獨的函數中,從而實現更好的代碼復用;
- 更好的類型推斷:組合式API對TypeScript的支持更友好,能提供更好的類型推斷和代碼提示;
- 清晰的邏輯分離:相比于Vue2的Options API,組合式API使得不同功能塊之間的邏輯更加清晰和分離;
樹形搖樹優化
:- 更小的打包體積:通過Tree-shaking,最終打包體積更小,加載速度更快;
- 高效的代碼分割:支持按需加載,減少初始加載時間,提高應用的性能;
- 優化的模塊引入:Vue3的模塊化設計使得Tree-shaking更加高效,進一步減少了不必要的代碼;
TypeScript支持?
:- 內置支持:Vue3核心完全用TypeScript重寫,內置支持TypeScript;
- 類型推斷:組合式API和Vue3的模塊化設計使得類型推斷更加準確;
- 開發體驗:對TypeScript的友好支持提升了開發體驗,減少了代碼錯誤,提高了代碼質量;
改進的響應性系統?
:- Proxy機制:使用Proxy替代Vue2中的Object.defineProperty,提升了性能和靈活性;
- 更細粒度的反應:響應性系統的改進使得組件更新更高效,減少了不必要的重新渲染;
- 更好的調試工具:改進的響應性系統提供了更強大的調試工具,幫助開發者更容易定位和解決問題;
增強的可維護性?
:- 模塊化設計:Vue3的核心庫和生態系統模塊化設計,使得升級和維護更加簡單;
- 更清晰的代碼結構:組合式API和單文件組件(SFC)使得代碼結構更加清晰,便于維護;
- 改進的開發工具:Vue3的開發者工具提供了更強大的功能,幫助開發者更好地管理和維護項目;
7.Vue3 的打包體積為什么更小?
Tree-shaking優化?
:Tree-shaking是一種通過靜態分析模塊依賴關系,去除未使用的代碼的技術。Vue3通過模塊化設計,允許構建工具如Webpack和Rollup更好地進行Tree-shaking,從而減少打包后的代碼體積?;Composition API?
:Vue3引入了Composition API,這種新的組件定義方式允許開發者以更靈活和簡潔的方式組織代碼。通過按需加載模塊和復用代碼片段,減少了不必要的代碼加載,進一步優化了代碼結構?;現代構建工具的使用?
:Vu 3充分利用了現代構建工具和技術,如Webpack、Rollup和Vite。這些工具支持高級優化技術,如代碼拆分、壓縮和混淆,自動壓縮和混淆代碼,減少文件大小?;更小的核心庫?
:Vue3的核心庫進行了精簡和優化,移除了一些不常用的功能,并將其作為獨立的插件提供。這種設計使得Vue3的核心庫在功能強大的同時也保持了較小的體積?;改進的響應式系統?
:Vue3采用了基于Proxy的響應式系統,相比Vue2的defineProperties,Proxy僅對所使用的屬性進行監聽,減少了無謂的開銷,提高了打包效率?;優化的組件渲染?
:Vue3在渲染過程中進行了大量優化,包括對模板中的靜態節點進行編譯優化、diff算法的優化等,進一步減少了最終打包的大小?;代碼壓縮和混淆?
:打包工具會對代碼進行壓縮和混淆處理,刪除空白字符、注釋和縮短變量名,同時通過混淆代碼使代碼難以閱讀,但不影響功能,從而減少文件大小?;
8.Vue3的設計目標是什么?
更小、更輕量
:Vue3通過移除一些不常用的API和引入tree-shaking 技術,實現了更小的打包體積。這意味著開發者可以只包含應用中實際使用的代碼,從而減少了不必要的代碼加載,提高了應用的加載速度和性能;更快、更高效
:Vue3在性能上進行了多項優化。例如,優化了diff算法,使其在處理虛擬DOM更新時更加高效;引入了靜態提升技術,將靜態節點在編譯時提升到更高的作用域,減少了運行時的計算;同時,事件監聽也進行了緩存優化,減少了不必要的監聽器注冊和注銷。此外,Vue3還對服務器端渲染(SSR)進行了改進,提升了渲染速度和整體性能;更友好、更易用
:Vue3引入了 Composition API,這一新特性提供了更靈活的邏輯復用和組織方式。開發者可以更加自由地組合和重用代碼邏輯,而不再受限于傳統的選項式 API。此外,Vue3提供了對TypeScript 的原生支持,使得類型檢查和代碼補全等開發體驗得到了顯著提升;增強可維護性
:Vue3通過重構和采用現代 JavaScript 特性(如 Proxy 和 Reflect),提高了框架內部的可維護性和可擴展性。這使得Vue框架本身更加健壯、易于理解和維護;促進生態系統的成長
:Vue3設計了新的 API 和工具,使得庫和工具的作者更容易為 Vue3提供或更新他們的產品。這有助于構建一個更加繁榮、活躍的 Vue 生態系統,為開發者提供更多選擇和更好的支持;
9.Vue3的項目結構有哪些調整?
Composition API
:Vue3引入了Composition API,這是對Vue2的Options API的一個補充和改進。Composition API允許開發者以更靈活的方式組織和復用代碼,特別是在處理大型組件時;單文件組件(SFC)的改進
:Vue3對單文件組件(SFC)提供了更好的支持,特別是通過<script setup>
標簽,它提供了一種編寫單文件組件的新方式;項目目錄結構的優化
:Vue3項目通常建議在項目目錄結構上進行一些優化,比如將組件、頁面、服務等邏輯分離到不同的文件夾中;全局狀態管理工具
:Vue3通常與狀態管理庫(如Vuex)結合使用,但Vue3本身也提供了全局狀態管理的內置支持(如Provide/Inject);
10.Vue3 模板語法有哪些改進?
指令優先級調整
:- 在Vue2中,v-for指令的優先級高于v-if指令。但在Vue3中,這一優先級得到了調整,v-if指令的優先級現在高于v-for指令。這一改變有助于開發者更好地控制渲染邏輯,避免不必要的性能開銷;
組合式API(Composition API)的引入
:- Vue3引入了Composition API,這是一種基于函數的API風格,允許開發者以更靈活的方式組織和復用代碼。與Vue2中的Options API相比,Composition API提供了更好的邏輯分離和復用性,特別是在處理復雜應用時,能夠顯著提升代碼的可維護性;
靜態節點優化
:- 在Vue3中,編譯器會對靜態節點進行標記,在更新時可以直接跳過這些靜態節點。這一優化減少了DOM操作,進一步提高了渲染性能;
異步刪除操作優化
:- 對于動態刪除操作,Vue3采用了異步隊列的方式進行,能夠將多個刪除操作合并為一個,從而減少DOM操作,提升性能;
Fragments優化
:- 在Vue2中,Fragments(片段)會引入額外的虛擬DOM層級,導致Diff算法需要進行更多的比較操作。而在Vue3中,對Fragments進行了優化,可以直接將其內部的內容合并到父級中,減少了虛擬DOM層級,提高了Diff算法的效率;
性能提升的其他方面
:- Vue3還對底層的響應式系統進行了重寫,使用了Proxy代理對象而非Vue2中的Object.defineProperty,這帶來了更好的性能和更低的內存消耗;
- Vue3引入了Patch flag的概念,用于標記組件在更新過程中的一些特殊情況,如組件的props發生變化或只需要強制更新等。這有助于在Diff算法中更快速地定位需要更新的組件,減少了比較的工作量;
模板語法的其他改進
:- Vue3保留了Vue2中廣泛使用的模板語法,如v-text、{{ }}插值表達式、v-html等,并進行了進一步的優化和完善;
- Vue3還支持v-model指令的雙向數據綁定,以及事件綁定指令和列表渲染指令等,為開發者提供了豐富的模板語法選擇;
11.Vue3中的組件生命周期鉤子有哪些變化?
移除的鉤子
:- beforeDestroy 和 destroyed 被替換為 beforeUnmount 和 unmounted;
- activated 和 deactivated(用于 )現在分別更名為 onActivate 和 onDeactivate;
新增的鉤子
:- onBeforeMount:在組件的掛載開始之前調用;
- onMounted:在組件的掛載完成后調用;
- onBeforeUpdate:在組件的更新之前調用;
- onUpdated:在組件的更新完成后調用;
- onBeforeUnmount:在組件卸載之前調用;
- onUnmounted:在組件卸載完成后調用;
- onErrorCaptured:當捕獲一個來自子孫組件的錯誤時調用;
- onRenderTracked 和 onRenderTriggered:這兩個鉤子用于調試,它們可以幫助你跟蹤組件渲染過程中依賴項的變化;
使用方法的變化
:- 在 Vue3 中,生命周期鉤子不再是通過字符串形式在選項中定義的,而是作為 Composition API 的一部分使用;
Composition API 的集成
:- Vue3 的 Composition API 允許你將組件的邏輯代碼更加模塊化和可重用,通過使用這些生命周期鉤子,你可以更容易地組織和維護復雜的組件邏輯;
12.請解釋Vue3中的響應式系統的工作原理?
Vue3 中的響應式系統通過 ES6 的 Proxy 對象和 Reactive API 實現高效的數據觀察和更新機制;
工作原理:
Proxy 對象
:Vue3 使用 Proxy 對象攔截對數據對象的操作,包括屬性讀取、賦值和刪除。當一個組件被創建時,Vue 為其 data 對象創建一個響應式代理對象。這個代理對象可以監聽到數據的變化,并在數據變化時更新視圖;Reactive API
:通過調用 reactive 函數,可以將普通的 JavaScript 對象轉換為響應式對象。當對象發生變化時,Vue 能夠檢測到并更新相應的視圖。此外,Vue3 還提供了 readonly 和 ref 函數來創建只讀和包裝過的響應式對象;依賴收集與追蹤
:當某個響應式屬性被訪問時,Vue 會記錄哪個組件或函數依賴了該屬性。當屬性值變化時,所有依賴該屬性的函數會被通知重新執行。依賴收集通過 Effect 函數實現;track 和 trigger
:在 get 攔截器中調用 track 記錄依賴,在 set 攔截器中調用 trigger 通知依賴更新;
13.Vue3中的虛擬DOM優化了哪些方面?
靜態提升
:- 原理:Vue3 編譯器會分析模板,識別出靜態節點,也就是那些內容不會隨數據變化而改變的節點。編譯器會將這些靜態節點提升到渲染函數外部,在首次渲染時創建它們,之后的渲染過程中直接復用這些節點,而不是每次都重新創建;
- 效果:這樣做大大減少了不必要的節點創建操作,降低了內存占用和 CPU 計算量,尤其在大型項目或者包含大量靜態內容的頁面中,性能提升效果顯著;
補丁標志
:- 原理:為每個虛擬DOM 節點添加特定的補丁標志,這些標志用于標記節點的哪些部分是動態的。在進行 Diff 算法比較新舊虛擬DOM時,Vue3 可以根據這些標志,只對有動態變化的部分進行詳細比較,而忽略靜態部分;
- 效果:極大地減少了Diff 過程中的計算量,提高了比較的速度,從而加快了虛擬DOM的更新效率;
靜態屬性緩存
:- 原理:對于靜態屬性,Vue3會將其緩存起來。在后續的渲染過程中,不會重新計算和比較這些靜態屬性,避免了重復工作;
- 效果:減少了額外的性能開銷,讓渲染過程更加高效;
基于 Proxy 的響應式系統優化
:- 原理:Vue3使用Proxy對象來實現響應式系統,相較于Vue2 中的 Object.defineProperty(),Proxy可以劫持整個對象的屬性訪問和修改操作,能夠更精準地感知數據的變化;
- 效果:當數據發生變化時,虛擬DOM可以更高效地接收到通知并進行更新,避免了Vue2中一些不必要的渲染,提高了整體性能;
片段支持
:- 原理:在 Vue3 中,組件可以返回多個根節點,形成片段。而在 Vue2中,組件必須有一個單一的根節點,這有時會導致需要添加額外的包裝元素;
- 效果:減少了不必要的包裝元素,使虛擬DOM結構更加簡潔,降低了虛擬DOM的復雜度,同時也讓模板代碼更加符合語義化,提升了開發的靈活性和代碼的可讀性;
14.簡述Composition API如何實現代碼邏輯的復用(hook) ?
定義hook
:- 創建一個JavaScript文件或直接在組件文件中定義一個以“use”為前綴命名的函數(例如useForm、useFetchData等);
- 在hook函數內部,使用Vue的響應式API(如ref、reactive、computed等)來定義和管理狀態;
- 封裝業務邏輯,如數據獲取、表單處理、事件監聽等,并返回需要暴露給組件的狀態和方法;
調用hook
:- 在組件的setup函數中,調用之前定義的hook函數;
- 將hook返回的狀態和方法解構并賦值給組件的局部變量,以便在模板中使用;
復用邏輯
:- 在不同的組件中,通過調用相同的hook函數來復用封裝好的邏輯;
- 這使得多個組件可以共享相同的業務邏輯,而無需重復編寫代碼;
15.簡述setup()函數在Vue3中起什么作用 ?
定義響應式狀態
:在 setup() 函數中,可以使用 Vue 提供的響應式 API(如 ref 和 reactive)來定義響應式狀態。ref 用于創建單個值的響應式引用,reactive 用于創建對象的響應式引用;使用計算屬性
:可以在 setup() 函數中定義計算屬性,使用 computed 函數來實現;聲明方法
:可以在 setup() 函數中定義方法,作為普通的 JavaScript 函數來聲明,并在返回對象中公開這些方法;使用生命周期鉤子
:在 setup() 函數中,可以使用 Vue 提供的生命周期鉤子函數來處理組件生命周期事件;使用依賴注入和提供
:在 setup() 函數中,可以使用 provide 和 inject API 來實現依賴注入;組合邏輯
:通過 setup() 函數,可以將邏輯組織成可復用的函數,這些函數可以在多個組件中共享;
16.簡述setup 方法和 setup 語法糖的區別 ?
-
語法結構層面
:- setup方法:它是Vue3組合式 API 標準的書寫方式。在組件對象中要顯式定義setup函數,函數接收props和context作為參數,并且要手動返回一個對象,對象里包含需要在模板中使用的數據和方法;
- setup語法糖:是 Vue3.2引入的語法糖。使用
<script setup>
標簽包裹代碼,無需顯式定義setup函數,在這個標簽內定義的變量和函數可以直接在模板中使用,無需手動返回;
-
API 使用方面
:- setup方法:使用 ref、reactive、defineProps 等API時,必須手動從vue中導入;
- setup語法糖:部分常用的API會自動注入,無需手動導入,像 ref、computed 等。不過,如果要使用一些高級API或者自定義的組合式函數,還是需要手動導入;
-
類型支持角度
:- setup方法:在結合TypeScript使用時,需要額外做一些配置來實現類型檢查和推導。例如,使用defineProps定義props時,要明確指定類型;
- setup語法糖:對TypeScript有更好的原生支持,類型推導更加自然和簡潔。在定義props 和emits時,可以直接使用類型注解;
-
適用場景差異
:- setup方法:適用于處理復雜的組件邏輯,當需要對組件的初始化過程進行細粒度控制,或者要和Vue2 的選項式API混合開發時,使用setup方法比較合適;
- setup語法糖:適合大多數日常開發場景,尤其是簡單組件的開發。它能減少樣板代碼,提高開發效率,讓開發者更專注于業務邏輯;
17.如何理解reactive、ref 、toRef 和 toRefs?
reactive:
定義
:reactive是Vue3中用于創建響應式對象或數組的方法;作用
:通過reactive創建的響應式對象或數組,其內部的所有屬性都會成為響應式的。當這些屬性發生變化時,依賴于它們的組件或計算屬性會自動更新;使用場景
:reactive更適合用于復雜的數據結構,如包含多個屬性的對象或數組;
ref:
定義
:ref是Vue3中用于創建響應式引用的方法;作用
:ref可以將一個普通的值(如字符串、數字、布爾值、對象、數組等)變成響應式的。當這個值發生變化時,依賴于它的組件或計算屬性會自動更新;使用場景
:ref更適合用于基本數據類型和需要單獨響應的復雜數據類型(如對象或數組);
toRef:
定義
:toRef是Vue3中的一個工具函數,用于將響應式對象的一個屬性轉換為一個獨立的ref對象;作用
:toRef可以保持原始屬性與轉換后的ref對象之間的響應式連接。修改ref對象的值會更新原始屬性,反之亦然;使用場景
:當需要將響應式對象的某個屬性單獨提取出來,同時保持其響應性時,可以使用toRef;
toRefs:
定義
:toRefs是Vue3中的另一個工具函數,用于將一個響應式對象轉換為一個普通對象,其中每個屬性都是一個ref對象;作用
:toRefs可以保持解構后的響應式對象的屬性仍然具有響應性;使用場景
:當需要解構響應式對象,并且希望解構后的屬性仍然是響應式的時,可以使用toRefs;
18.Vue3 中 computed 屬性的緩存機制是如何實現的?
在Vue3中,computed屬性的緩存機制是通過依賴追蹤、臟值標志以及重新計算來實現的。當定義一個computed屬性時,Vue會追蹤其依賴的響應式數據。如果依賴的數據沒有發生變化,再次訪問computed屬性時會直接返回緩存的值,避免不必要的計算。當依賴的數據發生變化時,會觸發computed屬性的重新計算,并更新緩存。這種機制通過依賴追蹤和臟值管理,有效地提高了應用的性能;
19.簡述Vue 3中的watch和watchEffect有何不同?
區別
觸發時機不同
:- watch:是惰性執行的。也就是說,它不會在組件創建時立即執行回調函數,只有當所監聽的數據源發生變化時,才會觸發回調;
- watchEffect:會立即執行一次回調函數,并且在回調函數執行過程中自動追蹤所依賴的響應式數據。之后,只要這些依賴數據發生變化,就會再次執行回調函數;
依賴指定方式不同
:- watch:需要明確指定要監聽的數據源。可以是單個響應式數據(如 ref 或 reactive 對象)、多個響應式數據,也可以是一個 getter 函數;
- watchEffect:不需要手動指定依賴,它會自動追蹤回調函數中使用的所有響應式數據;
回調參數不同
:- watch:回調函數可以接收新值和舊值作為參數,方便開發者對比數據的變化情況;
- watchEffect:回調函數沒有提供新值和舊值的參數,它更側重于執行副作用操作,比如更新DOM、發送網絡請求等;
使用場景
- watch:適用于需要根據特定數據變化執行操作的場景。由于它可以訪問新舊值,因此適合進行更復雜的操作,如深度監聽、監聽多個數據源等;
- watchEffect:適用于簡單的、與UI強相關的場景,或者不需要訪問之前數據的場景。它更加簡潔高效,因為自動收集依賴并立即執行,無需手動指定監聽的數據;
20.Vue3 中如何使用 provide 和 inject 實現依賴注入?它們的作用是什么?
使用方法:
provide的使用
:- provide函數用于在父組件或祖先組件中提供數據或方法;
- 它通常在父組件的setup函數中使用,接受兩個參數:key和value;
- key:注入名,可以是一個字符串或是一個Symbol,用于后代組件查找期望注入的值;
- value:提供的值,可以是任意類型,包括響應式的狀態;
inject的使用
:- inject函數用于在后代組件中注入由父組件或祖先組件提供的數據或方法;
- 它也接受兩個參數:key和defaultValue(可選);
- key:父組件提供值的key,必須與provide時使用的key相匹配;
- defaultValue:當沒有提供該依賴時使用的默認值,可以是具體的值,也可以是函數;
作用:
跨層級傳遞數據
:provide和inject允許我們在組件樹中跨層級地傳遞數據,而無需通過props逐層傳遞。這使得在深層嵌套的組件中訪問頂層組件的數據變得更加簡單和高效;實現組件間的解耦
:通過依賴注入,我們可以實現組件間的解耦。提供數據的組件和使用數據的組件之間不需要直接引用對方,從而降低了組件之間的耦合度,提高了代碼的可維護性和復用性;響應式數據傳遞
:provide和inject傳遞的數據可以是響應式的。當提供的數據發生變化時,所有依賴該數據的組件都會自動更新。這使得在多個組件之間共享響應式數據變得更加容易和高效;
21.Vue3中的Fragment是什么?它的用途是什么?
定義:
Fragment 是Vue3引入的虛擬節點,用于包裹多個子元素但不會渲染為真實DOM。它允許模板中存在多個根節點,解決了Vue2 必須有一個根元素的限制;
用途:
簡化頁面結構
:使用Fragment,開發者可以在不添加額外元素的情況下,將多個組件或元素包裹在一個邏輯容器中。這減少了不必要的DOM元素嵌套和深度,使得頁面結構更加簡潔;提高語義化
:Fragment允許組件直接返回多個所需元素,而無需額外的包裹元素,這避免了在某些情況下因包裹元素而破壞HTML結構的語義化,從而使頁面結構更加符合語義化標準;優化性能
:通過減少DOM層級,Fragment特性有助于提升頁面的渲染性能。避免不必要的DOM元素嵌套可以減少渲染和計算的工作量,從而提高頁面的響應速度;
22.什么是Tree-shaking?它在Vue 3中如何工作?
定義:
?Tree-shaking?是一種通過靜態代碼分析去除未使用代碼的技術,旨在減小項目體積,提高應用性能。在?Vue3?中,Tree-shaking通過其模塊化架構和ES模塊(ESM)的支持,實現了更高效的代碼優化;
基本原理:
Tree-shaking依賴于ES6模塊的靜態結構特性。ES6模塊使用靜態導入和導出語法,這使得編譯器可以在編譯階段確定模塊之間的依賴關系以及輸入和輸出的變量。通過靜態分析構建依賴圖,然后移除未使用的代碼,從而達到減小打包體積的目的?;
工作步驟:
?1. 模塊分析?
:在編譯階段,Vue3會分析代碼中引入的模塊,確定哪些模塊被實際使用,哪些模塊未被使用。這是通過靜態分析代碼中的導入語句(import)來實現的;
2?. 依賴關系構建?
:根據模塊之間的引用關系,構建一個模塊依賴圖。這個依賴圖描述了模塊之間的依賴關系,以及哪些模塊是被其他模塊所依賴的;
3?. 未使用模塊標記?
:通過遍歷模塊依賴圖,Vue3可以標記出哪些模塊未被使用。這些未使用的模塊將被視為可以被搖掉的“死代碼”;
?4. 代碼優化和刪除?
:在打包過程中,未使用的模塊代碼將被優化和刪除,從而減小最終打包生成的文件體積。這可以通過刪除未使用的模塊代碼、函數或變量來實現;
?5. 副作用處理?
:在搖樹過程中,需要處理一些可能產生副作用的代碼。例如,某些模塊可能在導入時執行一些初始化操作或注冊全局變量。Vue3會通過一些機制來識別和處理這些副作用,以確保搖樹過程的正確性;
23.Vue3中的Teleport是什么?它的用途是什么?
定義:
Teleport是Vue3引入的一個新特性,它允許我們將組件模板中的一部分內容渲染到DOM樹中的其他位置,而不改變組件的邏輯結構;
工作原理:
Teleport組件通過其to屬性指定目標容器,該屬性接受一個選擇器字符串或DOM元素作為值。當Teleport組件被渲染時,其內容會被“傳送”到指定的目標容器中,而邏輯結構和事件處理仍然保留在原始組件中。這意味著,盡管DOM位置發生了變化,但組件的狀態、方法和其他邏輯仍然屬于父組件管理;
用途:
減少 DOM 層級干擾?
:將如模態框、全局通知等需?脫離父組件層級?的內容渲染到頂層容器(如 body),避免父組件樣式(如 overflow: hidden)導致顯示異常?;?邏輯與樣式解耦?
:組件代碼仍保留在原位置維護邏輯(如數據、交互),僅渲染結果被傳送到目標位置,提升代碼可維護性?;支持動態渲染位置?
:通過動態綁定to屬性,可靈活切換渲染目標,適應不同場景需求(如多主題布局切換);解決 z-index 沖突?
:將懸浮組件(如 Tooltip、Dropdown)傳送到獨立層級,避免因父組件z-index限制導致覆蓋問題?;
24.Vue3中的Suspense是什么?如何使用它來處理異步組件?
定義:
Suspense是Vue3提供的一個內置組件,用于處理異步依賴的加載狀態。它可以在異步組件加載過程中顯示一個過渡內容,加載完成后顯示實際組件;
處理步驟:
-
?
定義異步組件?
:使用defineAsyncComponent函數來定義一個異步組件。這個函數接受一個返回Promise的加載函數,Promise 解析后會返回一個組件定義; -
使用 Suspense 包裹異步組件?
:
在模板中,使用 組件來包裹異步組件,并指定加載中和加載失敗時的回退內容;
25.Vue3 中 defineAsyncComponent 函數的參數和使用場景是什么?
defineAsyncComponent是Vue3中用于定義異步組件的一個函數。它允許開發者按需加載組件,即在組件實際被使用時才進行加載,這有助于減少應用的初始加載時間,提升用戶體驗;
核心使用場景?:
首屏性能優化?
: 拆分非關鍵組件代碼(如彈窗、復雜表單),減少首屏加載體積?;動態按需加載?
:按需加載用戶觸發的功能模塊(如彈窗、子頁面)?;第三方庫懶加載?
:減少初始加載時間,僅在使用時加載重量級庫(如富文本編輯器)?;代碼分割
:結合構建工具生成獨立代碼塊,優化緩存利用率?;
參數形式:
工廠函數?
:直接傳入動態import()實現懶加載?;配置對象?
:擴展加載狀態、錯誤處理、超時等邏輯?;
26.為什么Vue3選擇Proxy替代Object.defineProperty?
支持數組的直接監控
:- Object.defineProperty:無法直接監聽數組的變化(如 push、pop 等方法),需要通過包裹數組方法來間接實現;
- Proxy:可以直接攔截對數組的操作,包括增刪元素等操作,無需額外處理;
動態屬性的支持
:- Object.defineProperty:只能在對象創建時定義響應式屬性,后續添加或刪除屬性不會自動變為響應式;
- Proxy:可以攔截對象屬性的添加和刪除操作,使新添加的屬性自動成為響應式的,而不需要手動處理;
性能優化
:- Object.defineProperty:每次訪問或修改屬性時都會觸發getter和setter,這在處理大型對象時會導致性能問題;
- Proxy:通過攔截器機制,只有在實際發生屬性訪問或修改時才會觸發相應的邏輯,減少了不必要的開銷;
更豐富的攔截操作
:- Object.defineProperty:僅限于屬性的讀取和設置操作。
- Proxy:提供了更多的攔截操作,如get、set、apply、construct等,能夠更細粒度地控制對象的行為;
更好的兼容性和擴展性
:- Object.defineProperty:存在瀏覽器兼容性問題,并且某些情況下無法覆蓋所有場景(如不可枚舉屬性);
- Proxy:是ES6標準的一部分,具有更好的跨瀏覽器兼容性,并且可以通過自定義攔截器實現更多功能;
簡化框架內部實現
:- Object.defineProperty:由于其局限性,框架內部需要額外的邏輯來處理各種特殊情況;
- Proxy:簡化了框架內部的實現,使得代碼更加簡潔和易于維護;
27.簡述Vue3如何處理組件的異步加載 ?
使用 defineAsyncComponent
:defineAsyncComponent是Vue3專門用于定義異步組件的函數。它接收一個返回Promise的加載函數,該Promise會在組件加載完成后resolve。當組件需要被渲染時,Vue會調用這個加載函數來加載組件;使用Suspense 組件
:Suspense是Vue3新增的一個組件,它可以和異步組件配合使用,用于管理異步組件的加載狀態。Suspense組件有兩個插槽:#default 用于放置異步組件,#fallback 用于放置在異步組件加載過程中顯示的過渡內容;路由懶加載
:在Vue Router中,我們可以通過動態import來實現路由組件的異步加載。這種方式可以將不同路由的組件分割成不同的代碼塊,只有在用戶訪問相應路由時才會加載對應的組件代碼,從而減少初始加載的代碼量;
28.請描述一下Vue3中的虛擬DOM(Virtual DOM)和Diff算法的工作原理?
虛擬DOM:
定義
:
虛擬DOM是一種用JavaScript對象來表示真實DOM結構的技術。它并不是真實的DOM,而是一個輕量級的、對真實DOM的抽 象表示;工作原理
:- 當Vue組件的狀態發生變化時,Vue會重新渲染組件,生成新的虛擬DOM樹;
- Vue會比較新舊兩個虛擬DOM樹的差異,這個過程稱為“diff”;
- 根據diff的結果,Vue會計算出需要更新的真實DOM部分,并僅對這些部分進行更新,而不是重新渲染整個頁面;
優勢
:- 虛擬DOM將UI的狀態與DOM的操作解耦,避免了頻繁的真實DOM操作,從而提升了性能;
- 它允許開發者以聲明式的方式編寫代碼,提高了代碼的可讀性和可維護性;
Diff算法:
定義
:- Diff算法是一種用于比較兩個樹形結構并找出它們之間差異的算法。在Vue3中,它用于比較新舊兩個虛擬DOM樹;
工作原理
:- Diff算法的核心邏輯位于Vue的patch函數中。該函數會遞歸地比較新舊節點的類型、屬性和子節點;
- 如果節點類型相同,則進一步比較屬性和子節點;如果類型不同,則直接替換節點;
- 對于子節點的比較,Vue3采用了雙端比較策略,即同時從新舊子節點的兩端開始比較,以快速跳過相同部分;
- 如果子節點中有key屬性,Vue會使用哈希表來加速查找和匹配過程;
優化策略
:- Vue3在編譯階段會標記靜態節點,這些節點在渲染過程中不會被重新創建或比較,從而提高了性能;
- Vue3還引入了批量更新策略,將多次狀態變更合并為一次DOM操作,減少了不必要的重排和重繪;
優勢
:- Diff算法通過高效地比較新舊虛擬DOM樹并僅更新變化的部分,減少了不必要的DOM操作,提升了性能;
- 它使得Vue能夠快速地響應狀態變化并更新UI,提高了用戶體驗;
29.請解釋一下Vue3中的全局API和實例API的區別?
?全局API:
定義?
:全局API是定義在Vue構造函數或全局對象上的方法,它們可以在不依賴于Vue實例的情況下直接使用;作用?
:全局API主要用于配置Vue應用的全局行為,如創建Vue應用實例、注冊全局組件、全局指令、全局過濾器以及設置全局配置選項等。這些API在整個Vue應用中都是可用的,并且影響所有的Vue實例;
實例API:
定義?
:實例API是掛載在Vue實例上的方法或屬性,它們只能在Vue實例的上下文中訪問和使用;作用?
:實例API主要用于管理和操作Vue實例的狀態、屬性、方法以及生命周期鉤子等。這些API是Vue實例的核心部分,它們允許開發者在Vue實例的生命周期內進行各種操作,如數據綁定、事件處理、條件渲染等;
區別?:
作用域不同?
:全局API的作用域是整個Vue應用,而實例API的作用域是單個Vue實例。這意味著全局API可以在任何地方調用,而實例API只能在特定的Vue實例中調用;功能不同?
:全局API主要負責Vue應用的全局配置和實例創建,而實例API則負責Vue實例的狀態管理和行為控制。全局API提供了對Vue應用的全局設置和配置,而實例API則提供了對Vue實例的詳細控制和操作;使用時機不同?
:全局API通常在應用初始化階段使用,用于配置全局行為和創建Vue應用實例。而實例API則在Vue實例創建后使用,用于管理和操作Vue實例的狀態和行為;
30.請解釋一下Vue3中的靜態提升(Static Tree Hoisting)和Patch Flag的優化策略?
靜態提升:
定義
:靜態提升是Vue3編譯器的一項重要優化策略。它的核心思想是將模板中不變的部分(靜態節點)提升到渲染函數的外部,使它們只創建一次,避免每次重新渲染時都重復創建靜態內容;工作原理
:- 在編譯過程中,Vue3會分析模板中的靜態內容,并將其提升為一個單獨的靜態節點;
- 這些靜態節點在渲染函數外部被創建,并在每次渲染時復用,避免了重復創建和銷毀靜態內容所帶來的開銷;
優勢
:- 靜態提升可以顯著提升渲染性能,特別是對于包含大量靜態內容的頁面;
- 它減少了運行時動態開銷,使得Vue3在處理大型或復雜的應用時更加高效;
Patch Flag優化策略:
定義
:Patch Flag是Vue3為了優化虛擬DOM diff的一種機制。通過對每個動態節點進行標記,Vue可以精準地知道哪些節點是需要進行更新的,從而避免不必要的DOM操作;工作原理
:- 在編譯階段,Vue3會為動態節點打上Patch Flag,這些標記指示了節點的屬性和狀態變化;
- 在渲染過程中,Vue會根據這些標記來快速判斷哪些節點需要更新,哪些節點可以跳過;
- 通過精準更新,Vue3減少了無用的虛擬DOM對比,提升了整體性能;
優化細節
:- Vue3的Patch Flag系統支持多種標記類型,如靜態節點、動態節點、有狀態組件等,這些標記類型對應不同的處理邏輯;
- Vue3還引入了Block Tree等優化技術,進一步減少了不必要的更新范圍,提高了渲染效率;
優勢
:- Patch Flag優化策略使得Vue3能夠更高效地處理視圖更新,特別是在處理頻繁狀態變化的應用時;
- 它減少了不必要的DOM操作,降低diff算法的復雜度,從而提升了性能;
31.簡述Vue3跨域配置devServer參數的方法是什么 ?
- 在 vue.config.js 中配置 devServer.proxy,定義代理路徑(如 /api)和目標服務器地址;
- 啟用 changeOrigin 修改請求頭,確保跨域請求被后端接受;
- 使用 pathRewrite 按需重寫請求路徑(如刪除代理前綴)?;
32.Vue3 為什么不需要時間分片?
虛擬DOM的高效優化?
:
? - 智能差異算法?:Vue3的虛擬DOM采用更高效的Diff算法,僅對比并更新實際變化的節點,減少不必要的計算?;
? - 批量更新機制?:通過異步隊列合并多次數據變更,統一觸發渲染,降低DOM操作頻率?;
? - ?性能瓶頸場景少?:對于常規應用場景(非連續超100ms的CPU密集型計算),Vue3的虛擬DOM足以保證流暢性?;響應式系統的升級?
:
? - ?Proxy 替代 defineProperty?:Vue3的響應式系統基于 Proxy,支持深層嵌套對象和數組的自動監聽,減少手動優化需求?;
? - ?精準依賴追蹤?:僅更新依賴變化的組件,而非全量渲染,降低渲染壓力?;復雜度與收益的權衡?
:
? - ?實現成本高?:時間分片需要復雜的調度邏輯,與Vue3簡潔的設計理念沖突?;
?? - 邊際收益低?:Vue3的默認性能已足夠應對大部分場景,引入時間分片提升有限?;異步渲染與瀏覽器協作?
:
?? - 利用事件循環空閑時間?:Vue3的異步渲染策略將更新任務拆解到瀏覽器空閑時段,避免主線程阻塞?;
33如何解決 Vue3 中響應式丟失的問題?
解構賦值導致響應式丟失?
:- 原因?:直接解構 reactive對象或ref的 .value會提取原始值,脫離代理鏈?;
- 解決?:
- 使用toRefs或toRef包裹解構屬性,維持響應式引用?;
- 優先通過原對象訪問屬性(如 state.a),避免解構?;
對象整體替換破壞響應式?
- 原因?:直接替換reactive或ref的引用,導致代理失效?;
- 解決?:
- 修改對象屬性而非整體替換;
- 使用 ref 包裹對象,通過 .value 更新;
異步更新未正確使用響應式 API?
- 原因?:異步操作中直接賦值新數據,未通過代理觸發更新?;
- 解決?:
- 使用ref或合并屬性更新;
Props 解構或修改導致響應式斷裂?
- 原因?:解構props或直接修改非引用類型屬性,脫離父級響應式鏈?;
- 解決?:
- 使用 toRefs(props) 或 toRef(props, ‘key’) 保持響應性?;
- 通過emit通知父組件修改數據,避免直接操作props?;
34.Vue3中的工程化工具Vite是什么?它有什么優勢?
?定義?:Vite是一個由尤雨溪開發的面向現代前端開發的構建工具,專門為 Vue3項目設計,但也能很好地支持其他框架,如 React、Svelte等。它旨在提供更快的開發體驗,讓開發者能夠更高效地進行項目開發;
原理:
Vite基于原生ES模塊(ES Modules)實現,在開發環境下無需打包,直接利用瀏覽器的原生模塊加載功能,按需加載各個模塊。在生產環境中,Vite則使用Rollup進行打包,將代碼進行優化和壓縮;
?核心優勢?:
極速冷啟動?
:跳過傳統打包工具的預編譯階段,直接啟動開發服務器,啟動時間幾乎與項目規模無關?;高效熱更新
:僅編譯修改的模塊,瀏覽器直接加載更新后的代碼,響應速度達到毫秒級?;按需編譯?
:基于瀏覽器原生ESM,動態加載所需模塊,減少不必要的資源加載?;輕量插件系統?
:集成Rollup插件生態,同時提供專屬插件API,擴展性強?;生產優化?
:默認支持代碼分割、Tree-Shaking等優化策略,輸出高效生產代碼?;兼容現代瀏覽器?
:默認支持現代瀏覽器特性(如 ES6+),減少兼容性代碼冗余?;
與傳統打包工具對比:
Webpack
:Webpack是一個功能強大的打包工具,它可以處理各種復雜的項目需求,但配置相對復雜,啟動和熱更新速度較慢。而Vite配置簡單,啟動和熱更新速度快,更適合快速開發和小型項目;Rollup
:Rollup是一個專注于JavaScript模塊打包的工具,它的打包性能較好,但在開發環境下的體驗不如Vite。Vite在開發環境下無需打包,提供了更流暢的開發體驗;
適用場景?:
快速原型開發
:由于Vite的快速啟動和熱更新特性,非常適合快速搭建項目原型,讓開發者可以快速驗證想法;小型項目
:對于小型項目,Vite的簡單配置和高效性能可以幫助開發者更輕松地完成項目開發;現代前端框架項目
:Vite對Vue3、React 等現代前端框架有很好的支持,能夠充分發揮這些框架的優勢;
35.談談Pinia?
定義:
Pinia是Vue.js官方推薦的狀態管理庫,專為Vue3設計,同時也兼容Vue2。它旨在提供一種更簡潔、靈活且可擴展的方式來管理應用程序的狀態;
核心優勢:
輕量級
:Pinia的設計非常輕量,減少了不必要的復雜性,易于上手和使用;類型支持
:Pinia提供了良好的TypeScript支持,能夠更好地與TypeScript項目集成,提升開發體驗;模塊化
:Pinia支持模塊化的狀態管理,可以將狀態分割成多個store,便于管理和維護;響應式
:Pinia使用Vue3的響應式系統,確保狀態變化能夠自動更新到視圖中;簡潔的 API
:Pinia的API設計簡潔明了,易于理解和使用,減少了學習成本;插件支持
:Pinia支持插件,可以擴展其功能,滿足特定需求;開發者工具
:Pinia提供了與Vue Devtools的集成,方便開發者調試和查看狀態變化;支持 SSR
:Pinia可以與服務器端渲染(SSR)一起使用,適合構建現代化的應用;
Pinia 與 Vuex 核心對比?:
API 設計?
:- Vuex?:強制分離mutations(同步)與 actions(異步),需通過commit提交變更?;
- Pinia?:合并mutations至actions,允許直接修改state,簡化流程(如 this.count++)?;
模塊化方式?
:- ?Vuex?:需嵌套modules,易導致代碼臃腫?;
- ?Pinia?:獨立Store定義,天然扁平化,支持組合式邏輯復用?;
TS 支持?
:- ?Vuex?:需額外配置類型聲明,支持較弱?;
- ?Pinia?:原生類型推導,defineStore自動生成類型?;
響應式系統?
:- Vuex?:基于Vue2 的 Object.defineProperty?;
- ?Pinia?:基于Vue3的 Proxy,支持深層嵌套對象監聽?;
體積與性能?
:- Vuex?:約10KB,適合中大型項目?;
- ?Pinia?:僅1KB,輕量高效?;
適用場景?
:- ?Vuex?:適合需要嚴格數據流管控的遺留項目?;
- ?Pinia?:推薦用于Vue3新項目,靈活性高、開發效率快?;