首頁  >  文章  >  web前端  >  【整理分享】一些常見Vue面試題(附答案解析)

【整理分享】一些常見Vue面試題(附答案解析)

青灯夜游
青灯夜游轉載
2023-01-29 19:52:082711瀏覽

這次跟大家分享一些關於Vue的常見面試題,帶你梳理基礎知識,增強Vue知識儲備,值得收藏,快來看看吧!

【整理分享】一些常見Vue面試題(附答案解析)

Vue 常見面試題總結

MVVM模型?

MVVM,是Model-View-ViewModel的簡寫,其本質是MVC模型的升級版。其中Model 代表資料模型,View 代表看到的頁面,ViewModelViewModel之間的橋樑,資料會綁定到ViewModel層並自動將資料渲染到頁面中,視圖變化的時候會通知ViewModel層更新資料。以前是透過操作DOM來更新視圖,現在是資料驅動視圖

Vue的生命週期

每個Vue 元件實例在建立後都會經過一系列的初始化過程,這個過程中會執行叫做生命週期鉤子的函數,以便於使用者在特定的階段有機會新增自己的程式碼。

Vue 的生命週期可以分為8個階段:創建前後、掛載前後、更新前後、銷毀前後,以及一些特殊場景的生命週期。 Vue 3 中也新增了是3個用於偵錯和服務端渲染的場景。 【相關推薦:vuejs影片教學web前端開發

DOM##beforeUpdateupdatedbeforeDestroybeforeUnmount銷毀後,可用於一些計時器或訂閱的取消快取的元件啟動時##deactivated#deactivatederrorCaptured
Vue 2中的生命週期 Vue 3中的生命週期 描述
#beforeCreate beforeCreate 在建立前,此時datamethods的資料都還沒有初始化
created created 建立後,data中有值,尚未掛載,可以進行一些Ajax請求
beforeMount #beforeMount 掛載前,會找到虛擬DOM ,編譯成Render
mounted mounted mounted
#掛載後,已創建,可用於取得存取資料和DOM元素
#beforeUpdate 更新前,可用來取得更新前各種狀態
updated 更新後,所有狀態已是最新
在銷毀前,可用來一些計時器或訂閱的取消 ##destroyed unmounted
activated activated
keep-alive
keep-alive快取的元件停用時
######################################## #######errorCaptured#########擷取一個來自子孫元件的錯誤時呼叫###########—#########renderTracked# ########偵錯鉤子,響應式依賴被收集時呼叫############—#########renderTriggered#########偵錯鉤子,響應式依賴被觸發時呼叫############—##########serverPrefetch#########元件實例在伺服器上被渲染前呼叫############

父子元件的生命週期:

  • 載入渲染階段:父beforeCreate -> 父created -> 父beforeMount - > 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
  • 更新階段:父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
  • 銷毀階段:父beforeDestroy -> 子beforeDestroy -> 子destroyed ->父destroyed

Vue.$nextTick
在下次DOM 更新迴圈結束後執行延遲回呼。在修改資料之後立即使用這個方法,以取得更新後的 DOM。 nextTick 是Vue 提供的一個全域API,由於Vue 的非同步更新策略,導致我們對資料修改後不會直接體現在DOM 上,此時如果想要立即取得更新後的DOM 狀態,就需要藉助此方法。 Vue 在更新 DOM 時是非同步執行的。當資料發生變化,Vue 將開啟一個非同步更新佇列,並緩衝在同一事件循環中發生的所有資料變更。如果同一個 watcher 被多次觸發,只會被推入隊列一次。這種在緩衝時去除重複資料對於避免不必要的計算和 DOM 操作是非常重要的。 nextTick方法會在佇列中加入一個回呼函數,確保函數在前面的 DOM 操作完成後才呼叫。 使用場景:

如果想要在修改資料後立刻得到更新後的

DOM
    #結構,可以使用
  • Vue.nextTick ()


      created
    • 生命週期中進行
    • DOM
    • 運算 ##Vue 實例掛載過程中發生了什麼事?
    • 掛載過程指的是app.mount()過程,這是一個初始化過程,整體上做了兩件事:初始化
    • 建立更新機制初始化會建立元件實例、初始化元件狀態、建立各種響應式資料。 建立更新機制這一步驟會立即執行一次元件的更新函數,這會首次執行元件渲染函數並執行patch
    vnode
  • 轉換為
  • dom

    ; 同時首次執行渲染函數會建立它內部響應式資料和元件更新函數之間的依賴關係,這使得以後資料變更時會執行對應的更新函數。 Vue 的模版編譯原理

  • Vue 中有一個獨特的編譯器模組,稱為
compiler

,它的主要作用是將用戶編寫的template編譯為js中可執行的

render
    函數。
  • 在Vue 中,編譯器會先對

    template
    進行解析,這一步稱為

    parse###,結束之後得到一個JS對象,稱之為###抽象語法樹AST###;接著是對###AST###進行深加工的轉換過程,這一步稱為###transform###,最後將前面得到的###AST###產生JS程式碼,也就是###render###函數。 #########Vue 的響應式原則###############Vue 2 中的資料響應式會根據資料型別做不同的處理。如果是對象,則透過###Object.defineProperty(obj,key,descriptor)###攔截對象屬性訪問,當資料被存取或改變時,感知並作出反應;如果是數組,則透過覆寫數組原型的方法,擴展它的7個變更方法(push、pop、shift、unshift、splice、sort、reverse),使這些方法可以額外的做更新通知,從而做出回應。 ###缺點:#########初始化時的遞歸遍歷會造成效能損失;#######通知更新程序需要維護大量###dep### 實例和###watcher# ## 實例,額外佔用記憶體較多;######新增或刪除物件屬性無法攔截,需要透過###Vue.set### 及###delete### 這樣的API 才能生效; ######對於###ES6###中新產生的###Map###、###Set###這些資料結構不支援。 ###############Vue 3 中利用###ES6###的###Proxy###機制代理程式需要回應化的資料。可以同時支援物件和數組,動態屬性增、刪除都可以攔截,新增資料結構均支持,物件嵌套屬性運行時遞歸,用到時才代理,也不需要維護特別多的依賴關係,效能取得很大進步。 ###############虛擬DOM################概念:###虛擬DOM,顧名思義就是虛擬的DOM對象,它本身就是一個JS對象,只不過是透過不同的屬性去描述一個視圖結構。 ###
  • 虛擬DOM的好處:
    (1) 效能提升
    直接操作DOM是有限制的,一個真實元素上有很多屬性,如果直接對其進行操作,同時會對很多額外的屬性內容進行了操作,這是不必要的。如果將這些操作轉移到JS物件上,就會簡單很多。另外,操作DOM的代價是比較昂貴的,頻繁的操作DOM容易造成頁面的重繪和回流。如果透過抽象VNode進行中間處理,可以有效減少直接操作DOM次數,進而減少頁面的重繪和回流。
    (2) 方便跨平台實作
    同一VNode節點可以渲染成不同平台上對應的內容,例如:渲染在瀏覽器是DOM元素節點,渲染在Native(iOS、Android)變成對應的控制項。 Vue 3 中允許開發者基於VNode實作自訂渲染器(renderer),以便於針對不同平台進行渲染。

  • 結構:
    沒有統一的標準,一般包括tagpropschildren三項。
    tag:必選。就是標籤,也可以是組件,或是函數。
    props:非必選。就是這個標籤上的屬性和方法。
    children:非必選。就是這個標籤的內容或子節點。如果是文字節點就是字串;如果有子節點就是數組。換句話說,如果判斷children是字串的話,就表示一定是文字節點,這個節點一定沒有子元素。

diff 演算法

#1、概念:

diff演算法是一種對比演算法,透過比較舊的虛擬DOM和新的虛擬DOM,得出是哪個虛擬節點發生了改變,找出這個虛擬節點並只更新這個虛擬節點所對應的真實節點,而不用更新其他未發生改變的節點,實現精準地更新真實DOM,進而提高效率。

2、比較方式:

diff演算法的整體策略是:深度優先,同層比較。比較只會在同層級進行, 不會跨層級比較;比較的過程中,循環從兩邊向中間收攏。

  • 首先判斷兩個節點的tag是否相同,不同則刪除該節點重新建立節點進行替換。
  • tag相同時,先取代屬性,再對比子元素,分為下列幾種情況:
    • 新舊節點都有子元素時,採用雙指標方式進行對比。新舊頭尾指標進行比較,循環向中間靠攏,根據情況呼叫patchVnode進行patch重複流程、呼叫createElem建立一個新節點,從雜湊表尋找key一致的VNode節點再分狀況運算。
    • 新節點有子元素,舊節點沒有子元素,則將子元素虛擬節點轉換成真實節點插入即可。
    • 新節點沒有子元素,舊節點有子元素,則清空子元素,並設定為新節點的文字內容。
    • 新舊節點都沒有子元素時,即都為文字節點,則直接對比文字內容,不同則更新。

Vue中key的作用?

key的作用主要是為了更有效率的更新虛擬 DOM

Vue 判斷兩個節點是否相同時,主要是判斷兩者的key元素類型tag。因此,如果不設定key,它的值就是 undefined,則可能永遠認為這是兩個相同的節點,只能去做更新操作,將造成大量的 DOM 更新操作。

為什麼元件中的 data 是一個函數?

在 new Vue() 中,可以是函數也可以是對象,因為根實例只有一個,不會產生資料污染。

在元件中,data 必須為函數,目的是為了防止多個元件實例物件之間共用一個data,產生資料污染;而採用函數的形式,initData 時會將其作為工廠函數都會傳回全新的data 物件。

Vue 中元件間的通訊方式?

  • 父子元件通訊:

    父傳遞資料是透過props,子向父是透過$emit 觸發事件;透過父鏈/子鏈也可以通訊($parent/$children);ref也可以存取元件實例;provide/inject;$attrs/$listeners

  • 兄弟元件通訊:

    全域事件匯流排EventBusVuex

  • 跨層級元件通訊:

    全域事件匯流排EventBusVuexprovide/ inject

v-show 和 v-if 的差別?

  • 控製手段不同。 v-show是透過為元素添加css 屬性display: none,但元素仍然存在;而v-if控制元素顯示或隱藏是將元素整個新增或刪除。

  • 編譯過程不同。 v-if切換有一個局部編譯/卸載的過程,切換過程中適當的銷毀和重建內部的事件監聽和子元件;v-show只是簡單的基於 css 切換。

  • 編譯條件不同。 v-if是真正的條件渲染,它會確保在切換過程中條件區塊內的事件監聽器和子元件適當地被銷毀和重建,渲染條件為假時,並不做操作,直到為真才渲染。

  • 觸發生命週期不同。 v-show由false 變成true 的時候不會觸發元件的生命週期;v-if由false 變成true 的時候,觸發元件的beforeCreatecreatedbeforeMountmounted鉤子,由true 變成false 的時候觸發元件的beforeDestorydestoryed鉤子。

  • 效能消耗不同。 v-if有較高的切換消耗;v-show有較高的初始渲染消耗。

使用場景:
如果需要非常頻繁地切換,則使用v-show較好,如:手風琴選單,tab 頁籤等; 如果在執行時間條件很少改變,則使用v-if較好,如:使用者登入之後,根據權限不同來顯示不同的內容。

computed 和 watch 的差別?

  • computed計算屬性,依賴其它屬性計算值,內部任一依賴項的變化都會重新執行該函數,計算屬性有緩存,多次重複使用計算屬性時會從快取中取得回傳值,而計算屬性必須要有return關鍵字。
  • watch偵聽某一資料的變化從而觸發函數。當資料為物件類型時,物件中的屬性值變更時需要使用深度偵聽deep屬性,也可在頁面第一次載入時使用立即偵聽immdiate屬性。

運用場景:
計算屬性一般用在範本渲染中,某個值是依賴其它回應物件甚至是計算屬性而來;而偵測屬性適用於觀測某個值的變化去完成一段複雜的業務邏輯。

v-if 和 v-for 為什麼不建議放在一起使用?在

Vue 2 中,v-for的優先權比v-if高,這表示v-if將分別重複運行於每一個v-for循環。如果要遍歷的陣列很大,而真正要展示的資料很少時,將造成很大的效能浪費。

Vue 3 中,則完全相反,v-if的優先權高於v-for,所以v-if執行時,它所呼叫的變數還不存在,會導致異常。

通常有兩種情況導致要這樣做:

  • 為了過濾清單中的項目,例如:v-for = "user in users" v-if = "user.active"。這種情況,可以定義一個計算屬性,讓其傳回過濾後的清單即可。
  • 為了避免渲染本來應該隱藏的列表,例如v-for = "user in users"  v-if = "showUsersFlag"。這種情況,可以將v-if移至容器元素上或在外麵包一層template即可。

$set

可手動新增響應式數據,解決資料變更檢視未更新問題。當在專案中直接設定數組的某一項的值,或是直接設定物件的某個屬性值,會發現頁面並沒有更新。這是因為Object.defineProperty()的限制,監聽不到資料變化,可透過this.$set(數組或對象,數組下標或對象的屬性名,更新後的值)解決。

keep-alive 是什麼?

  • 作用:實作元件緩存,保持元件的狀態,避免反覆渲染導致的效能問題。
  • 工作原理:Vue.js 內部將 DOM 節點,抽象化成了一個個的 VNode 節點,keep-alive元件的快取也是基於 VNode 節點的。它將滿足條件的元件在 cache 物件中快取起來,重新渲染的時候再將 VNode 節點從 cache 物件中取出並渲染。
  • 可以設定以下屬性:
    include:字串或正規則,只有名稱符合的元件會被快取。
    exclude:字串或正規則,任何名稱符合的元件都不會被快取。
    max:數字,最多可以快取多少元件實例。
    符合先檢查元件的name選項,如果name選項不可用,則符合它的局部註冊名稱(父元件components選項的鍵值),匿名元件不能被匹配。

設定了keep-alive快取的元件,會多出兩個生命週期鉤子:activateddeactivated
第一次進入元件時:beforeCreate --> created --> beforeMount --> mounted --> activated --> beforeUpdate --> updated --> deactivated
再次進入元件時:activated --> beforeUpdate --> updated --> deactivated

##mixin

mixin(混入), 它提供了一種非常靈活的方式,來分發Vue 元件中的可重複使用功能。

使用場景: 不同元件中常會用到一些相同或相似的程式碼,這些程式碼的功能相對獨立。可以透過mixin 將相同或相似的程式碼提出來。

劣勢:

  • 變數來源不明確

  • 多mixin 可能會造成命名衝突(解決方式:Vue 3的組合API)

  • mixin 和元件坑出現多對的關係,使專案複雜度變高。

插槽

slot插槽,一般在元件內部使用,封裝元件時,元件內部不在確定該位置是以何種形式的元素展示時,可以透過slot佔據這個位置,該位置的元素需要父元件以內容形式傳遞過來。 slot分為:

  • 預設插槽:子元件用標籤來決定渲染的位置,標籤裡面可以放DOM結構作為後備內​​容,當父元件在使用的時候,可以直接在子元件的標籤內寫入內容,該部分內容將插入子元件的 標籤位置。如果父元件使用的時候沒有往插槽傳入內容,後備內容就會顯示在頁面。
  • 具名插槽:子元件用name屬性來表示插槽的名字,沒有指定name的插槽,會有隱含的名稱叫做default。父元件中在使用時在預設插槽的基礎上透過v-slot指令指定元素需要放在哪個插槽中,v-slot值為子元件插槽name屬性值。使用v-slot指令指定元素放在哪個插槽中,必須配合