【面經系列】Vue面經

【Q1】談談你對 MVVM 的理解

MVVMModel-View-ViewModel 的縮寫,其中:

  • Model 代表數據模型,可以在 Model 中定義數據修改和操作的業務邏輯。可以把 Model 稱爲數據層,因爲它僅僅關注數據本身,不關心其他行爲。
  • View 是用戶操作的界面,可以稱爲視圖層。負責視圖展現工作。當 ViewModelModel 進行更新的時候,會通過數據綁定更新到 View
  • ViewModel 稱爲業務邏輯層,是數據層和視圖層通信的橋樑。View 需要什麼數據,ViewModel 要提供這個數據,有些操作也需要 ViewModel 的響應。

【總結】:MVVM 模式簡化了界面與業務的依賴,解決了數據頻繁更新。在 MVVM 中,利用雙向綁定技術,使得 Model 變化時,ViewModel 會自動更新,而 ViewModel 變化時,View 也會自動更新。

【Q2】談談你對SPA的理解

SPA 應用僅在頁面首次初始化時加載相應的 HTMLCSSJS 。一旦完成加載,就不會因爲用戶的操作而進行頁面的重新加載,取而代之的是利用前端路由實現內容的變換。

【優點】:

  • 前後端職責更好的分離,架構清晰
  • 用戶體驗好,服務器相對壓力小

【缺點】:

  • 首次加載耗時久
  • SEO 難優化

【Q3】談談你對響應式的理解

通過數據模型(普通的 JS 對象)來驅動視圖的更新,就是響應式。

以實例的 data 選項爲例,當我們把一個普通的 JS 對象傳入 Vue 實例作爲 data 時,Vue 將遍歷這個對象的所有屬性,然後通過 Object.defineProperty (vue 2.x)或者 Proxy (vue 3.x)定義屬性的 gettersetter ,從而讓 Vue 能夠追蹤當這些屬性訪問與修改。具體是怎麼追蹤的呢?每個組件實例都對應一個 watcher 實例,它會在組件渲染的過程中把接觸過的數據記錄爲依賴,這個過程也稱爲依賴收集,然後當依賴的 setter 觸發時,就會通知 watcher ,從而使他們關聯的組件重新渲染。

在這裏插入圖片描述

【Q4】你知道 Vue 雙向數據綁定的原理嗎?

Vue 雙向數據綁定是指:數據變化更新視圖,視圖變化更新數據,例如輸入框輸入內容變化時,data 中對應的數據同步變化,data 中綁定的數據變化時,輸入框的內容同步變化。

Vue 主要通過4個部分來實現雙向數據綁定:

  • 監聽器 Observer :對數據對象進行遍歷,利用 Object.defineProperty() 在屬性上都加上 gettersetter ,從而監聽數據的變化。
  • 解析器 Compile :解析模板指令,將模板中的變量都替換成數據,並將每個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變化就會調用更新函數進行更新。
  • 訂閱者 Watcher :訂閱者是監聽器和解析器之間通信的橋樑,主要任務是訂閱監聽器中的屬性值變化的消息,當收到屬性值變化的消息時,觸發解析器中對應的更新函數。
  • 訂閱器 Dep :訂閱器採用發佈-訂閱設計模式,用來收集訂閱者 Watcher 對監聽器 Observer 和 訂閱者 Watcher 進行統一管理。

【Q5】爲什麼 Vue 要採用異步渲染?異步渲染是如何實現的?

如果不採用異步渲染,那麼每次更新數據都會進行重新渲染,這會對性能大打折扣,異步渲染是提高性能的手段之一。

只要監聽到數據變化,Vue 將開啓一個隊列,並緩衝在同一個事件循環中發生的所有數據變更。如果同一個 watcher 被多次觸發,只會被推入到隊列中一次。然後,在下一個事件循環中,Vue 刷新隊列並執行實際工作。Vue 內部對異步隊列常使用原生的 Promise.thenMutationObserversetImmediate。如果環境不支持,則採用 setTimeout(fun,0)

【Q6】Vue 是如何檢測數組的變化

Vue 官方中,提供了7個操作數組的方法:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

用於 “響應式” 的操作數組,也就是說,通過以上7個方法改變數組的元素,這會導致 data 中的數據變化,從而導致視圖發生變化。除此以外,還可以通過 “新數組” 替換 “舊數組” 的方式來觸發視圖層的改變。但是,千萬不能通過索引直接改變一個數組,這樣不會引起視圖層的改變,只是單純的改變了數據。還有,不能通過修改數組長度來刪除元素。

Vuedata 中的數組進行了原型鏈重寫,指向了自己所定義的數組原型方法(也就是說上面的7個方法是Vue重寫過的),從而實現了通過這些方法改變數組就可以通知視圖層更新的效果。

【Q7】談談你對 Vue 生命週期的理解

Vue 實例有一個完整的生命週期,也就是從開始創建、初始化數據、編譯模板、掛載DOM、渲染、更新、卸載等一些列過程,就是生命週期。

生命週期可大致分爲 8 個階段:實例創建前/後,掛載前/後,更新前/後,銷燬前/後,分別對應8個回調鉤子。

  • 實例創建前。beforeCreate() —— vue 實例的掛載元素 $el 和數據對象 data 都是 undefined ,還未進行初始化。
  • 實例創建後。created() —— 完成了 data 數據初始化,但未掛載。
  • 掛載前。beforeMount —— vue 實例的 $eldata 都初始化了,相關的 render 函數首次被調用。實例已完成以下配置:編譯模板,把 data 裏面的數據和模板生成 html。但是此時沒有掛載到 html 元素上!!!
  • 掛載後。mounted —— el$el 替換,並掛載到 html 元素上。
  • 更新前。beforeUpdate —— 在數據更新之前調用。
  • 更新後。updated —— 此時組件 DOM 已經更新,所以可以執行依賴於 DOM 的操作。
  • 銷燬前。beforeDestroy —— 實例銷燬前調用
  • 銷燬後。destroyed —— 實例銷燬後調用。

【Q8】v-showv-if 有什麼區別

兩者都用於控制 “顯示/隱藏” 元素,v-if 是真正的條件渲染,如果條件爲假,則該元素不會被掛載到 DOM 樹上,只有當條件爲真時才進行渲染。v-show 本質是控制 cssdisplay 屬性來進行顯示隱藏的,不管初始條件是什麼,該元素都會被渲染。

【Q9】 Vue 是單向數據流還是雙向的?

官方是這樣來介紹的:所有的 prop 都使得其父子 prop 之間形成了一個單向下行綁定,父級 prop 的更新會向下流動到子組件中,但是反過來則不行。這也說明了不能在子組件中改變 propprop 永遠都是隻讀的。如果非得改變 prop 的話,可以考慮在子組件中通過計算屬性來修改。

每次父組件發生更新時,子組件中所有的 prop 都將會刷新爲最新的值。

【Q10】組件通信的方式你知道哪些?

【方式一:props/$emit】

【父組件向子組件通信】
父組件直接通過標籤屬性的形式將數據傳遞給子組件,子組件通過實例的 props 屬性即可獲取到父組件傳遞過來的數據。

【子組件向父組件通信】
在子組件中,通過實例方法 this.$emit() 向父組件發送信息,將自己的數據傳遞給父組件。

該方法接收兩個參數,第一個是事件名,第二個是攜帶的數據。

【方式二:provide/inject】

父組件使用 provide 向下提供數據,其下所有子組件都可以通過 inject 注入,不管中間隔了多少代,都可以注入多個來自不同父級提供的數據。

providevue 實例的配置選項,它是一個對象或者一個返回對象的函數。

inject 是一個字符串數組,或一個對象。

【方式三:$parent

$parent 可以從一個子組件訪問父組件的實例。它是實例的屬性,可以通過實例直接訪問。

【方式四:$refs

通過 ref 標籤屬性可以標記一個子組件,然後通過實例的 $refs 來訪問具體的子組件實例。

【方式五:vuex

通過 vuex 進行狀態的統一管理。

未完,一直更

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章