前端vue面試題,附答案


前端vue面試題,附答案

vue視頻教程系列:

騰訊Vue實戰問卷網站視頻教程

視頻教程:點擊查看

完整教程目錄:點擊查看

最新 Vue+Spring 旅游項目

視頻教程:點擊查看

完整教程目錄:點擊查看

Vue3.0(正式版) + TS 仿知乎專欄企業級項目

視頻教程:點擊查看

完整教程目錄:點擊查看

Vue3.0+TS打造企業級組件庫 前端中高級開發者必修課

視頻教程:點擊查看

完整教程目錄:點擊查看

基於VantUI的Vue移動端電商項目實戰

視頻教程:點擊查看

完整教程目錄:點擊查看

vue 中使用了哪些設計模式

1.工廠模式 - 傳入參數即可創建實例

虛擬 DOM 根據參數的不同返回基礎標簽的 Vnode 和組件 Vnode

2.單例模式 - 整個程序有且僅有一個實例

vuex 和 vue-router 的插件注冊方法 install 判斷如果系統存在實例就直接返回掉

3.發布-訂閱模式 (vue 事件機制)

4.觀察者模式 (響應式數據原理)

5.裝飾模式: (@裝飾器的用法)

6.策略模式 策略模式指對象有某個行為,但是在不同的場景中,該行為有不同的實現方案-比如選項的合並策略

Vue模版編譯原理知道嗎,能簡單說一下嗎?

簡單說,Vue的編譯過程就是將template轉化為render函數的過程。會經歷以下階段:

  • 生成AST樹
  • 優化
  • codegen

首先解析模版,生成AST語法樹(一種用JavaScript對象的形式來描述整個模板)。 使用大量的正則表達式對模板進行解析,遇到標簽、文本的時候都會執行對應的鈎子進行相關處理。

Vue的數據是響應式的,但其實模板中並不是所有的數據都是響應式的。有一些數據首次渲染后就不會再變化,對應的DOM也不會變化。那么優化過程就是深度遍歷AST樹,按照相關條件對樹節點進行標記。這些被標記的節點(靜態節點)我們就可以跳過對它們的比對,對運行時的模板起到很大的優化作用。

編譯的最后一步是將優化后的AST樹轉換為可執行的代碼

Vue.js的template編譯

簡而言之,就是先轉化成AST樹,再得到的render函數返回VNode(Vue的虛擬DOM節點),詳細步驟如下:

首先,通過compile編譯器把template編譯成AST語法樹(abstract syntax tree 即 源代碼的抽象語法結構的樹狀表現形式),compile是createCompiler的返回值,createCompiler是用以創建編譯器的。另外compile還負責合並option。

然后,AST會經過generate(將AST語法樹轉化成render funtion字符串的過程)得到render函數,render的返回值是VNode,VNode是Vue的虛擬DOM節點,里面有(標簽名、子節點、文本等等)

了解nextTick嗎?

異步方法,異步渲染最后一步,與JS事件循環聯系緊密。主要使用了宏任務微任務(setTimeoutpromise那些),定義了一個異步方法,多次調用nextTick會將方法存入隊列,通過異步方法清空當前隊列。

computed 的實現原理

computed 本質是一個惰性求值的觀察者。

computed 內部實現了一個惰性的 watcher,也就是 computed watcher,computed watcher 不會立刻求值,同時持有一個 dep 實例。

其內部通過 this.dirty 屬性標記計算屬性是否需要重新求值。

當 computed 的依賴狀態發生改變時,就會通知這個惰性的 watcher,

computed watcher 通過 this.dep.subs.length 判斷有沒有訂閱者,

有的話,會重新計算,然后對比新舊值,如果變化了,會重新渲染。 (Vue 想確保不僅僅是計算屬性依賴的值發生變化,而是當計算屬性最終計算的值發生變化時才會觸發渲染 watcher 重新渲染,本質上是一種優化。)

沒有的話,僅僅把 this.dirty = true。 (當計算屬性依賴於其他數據時,屬性並不會立即重新計算,只有之后其他地方需要讀取屬性的時候,它才會真正計算,即具備 lazy(懶計算)特性。)

Vue 為什么要用 vm.$set() 解決對象新增屬性不能響應的問題 ?你能說說如下代碼的實現原理么?

1)Vue為什么要用vm.$set() 解決對象新增屬性不能響應的問題

  1. Vue使用了Object.defineProperty實現雙向數據綁定
  2. 在初始化實例時對屬性執行 getter/setter 轉化
  3. 屬性必須在data對象上存在才能讓Vue將它轉換為響應式的(這也就造成了Vue無法檢測到對象屬性的添加或刪除)

所以Vue提供了Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value)

2)接下來我們看看框架本身是如何實現的呢?

Vue 源碼位置:vue/src/core/instance/index.js

export function set (target: Array<any> | Object, key: any, val: any): any {
  // target 為數組  
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    // 修改數組的長度, 避免索引>數組長度導致splcie()執行有誤
    target.length = Math.max(target.length, key)
    // 利用數組的splice變異方法觸發響應式  
    target.splice(key, 1, val)
    return val
  }
  // key 已經存在,直接修改屬性值  
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  // target 本身就不是響應式數據, 直接賦值
  if (!ob) {
    target[key] = val
    return val
  }
  // 對屬性進行響應式處理
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val
}

我們閱讀以上源碼可知,vm.$set 的實現原理是:

  1. 如果目標是數組,直接使用數組的 splice 方法觸發相應式;
  2. 如果目標是對象,會先判讀屬性是否存在、對象是否是響應式,
  3. 最終如果要對屬性進行響應式處理,則是通過調用 defineReactive 方法進行響應式處理

defineReactive 方法就是 Vue 在初始化對象時,給對象屬性采用 Object.defineProperty 動態添加 getter 和 setter 的功能所調用的方法

v-show 與 v-if 有什么區別?

v-if真正的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子組件適當地被銷毀和重建;也是惰性的:如果在初始渲染時條件為假,則什么也不做——直到條件第一次變為真時,才會開始渲染條件塊。

v-show 就簡單得多——不管初始條件是什么,元素總是會被渲染,並且只是簡單地基於 CSS 的 “display” 屬性進行切換。

所以,v-if 適用於在運行時很少改變條件,不需要頻繁切換條件的場景;v-show 則適用於需要非常頻繁切換條件的場景。

Vue 組件間通信有哪幾種方式?

​ Vue 組件間通信是面試常考的知識點之一,這題有點類似於開放題,你回答出越多方法當然越加分,表明你對 Vue 掌握的越熟練。Vue 組件間通信只要指以下 3 類通信:父子組件通信、隔代組件通信、兄弟組件通信,下面我們分別介紹每種通信方式且會說明此種方法可適用於哪類組件間通信。

(1)props / $emit 適用 父子組件通信

這種方法是 Vue 組件的基礎,相信大部分同學耳聞能詳,所以此處就不舉例展開介紹。

(2)ref$parent / $children 適用 父子組件通信

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件實例
  • $parent / $children:訪問父 / 子實例

(3)EventBus ($emit / $on) 適用於 父子、隔代、兄弟組件通信

這種方法通過一個空的 Vue 實例作為中央事件總線(事件中心),用它來觸發事件和監聽事件,從而實現任何組件間的通信,包括父子、隔代、兄弟組件。

(4)$attrs/$listeners 適用於 隔代組件通信

  • $attrs:包含了父作用域中不被 prop 所識別 (且獲取) 的特性綁定 ( class 和 style 除外 )。當一個組件沒有聲明任何 prop 時,這里會包含所有父作用域的綁定 ( class 和 style 除外 ),並且可以通過 v-bind="$attrs" 傳入內部組件。通常配合 inheritAttrs 選項一起使用。
  • $listeners:包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器。它可以通過 v-on="$listeners" 傳入內部組件

(5)provide / inject 適用於 隔代組件通信

祖先組件中通過 provider 來提供變量,然后在子孫組件中通過 inject 來注入變量。 provide / inject API 主要解決了跨級組件間的通信問題,不過它的使用場景,主要是子組件獲取上級組件的狀態,跨級組件間建立了一種主動提供與依賴注入的關系。

(6)Vuex 適用於 父子、隔代、兄弟組件通信

Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。每一個 Vuex 應用的核心就是 store(倉庫)。“store” 基本上就是一個容器,它包含着你的應用中大部分的狀態 ( state )。

  • Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那么相應的組件也會相應地得到高效更新。
  • 改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化。

Vue 中的 key 到底有什么用?

key 是給每一個 vnode 的唯一 id,依靠 key,我們的 diff 操作可以更准確、更快速 (對於簡單列表頁渲染來說 diff 節點也更快,但會產生一些隱藏的副作用,比如可能不會產生過渡效果,或者在某些節點有綁定數據(表單)狀態,會出現狀態錯位。)

diff 算法的過程中,先會進行新舊節點的首尾交叉對比,當無法匹配的時候會用新節點的 key 與舊節點進行比對,從而找到相應舊節點.

更准確 : 因為帶 key 就不是就地復用了,在 sameNode 函數 a.key === b.key 對比中可以避免就地復用的情況。所以會更加准確,如果不加 key,會導致之前節點的狀態被保留下來,會產生一系列的 bug。

更快速 : key 的唯一性可以被 Map 數據結構充分利用,相比於遍歷查找的時間復雜度 O(n),Map 的時間復雜度僅僅為 O(1)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM