0.那你能講一講MVVM嗎?
1.簡單說一下Vue2.x響應式數據原理
-Vue在初始化數據時,會使用Object.defineProperty重新定義data中的所有屬性,當頁面使用對應屬性時,首先會進行依賴收集(收集當前組件的watcher)如果屬性發生變化會通知相關依賴進行更新操作(發佈訂閱)。
.那你知道Vue3.x響應式數據原理嗎?
Proxy只會代理對象的第一層,那麼Vue3又是怎樣處理這個問題的呢?
監測數組的時候可能觸發多次get/set,那麼如何防止觸發多次呢?
-我們可以判斷key是否爲當前被代理對象target自身屬性,也可以判斷舊值與新值是否相等,只有滿足以上兩個條件之一時,纔有可能執行trigger。
3.再說一下vue2.x中如何監測數組變化
4.nextTick知道嗎,實現原理是什麼?
在下次 DOM 更新循環結束之後執行延遲迴調。nextTick主要使用了宏任務和微任務。根據執行環境分別嘗試採用
定義了一個異步方法,多次調用nextTick會將方法存入隊列中,通過這個異步方法清空當前隊列。
關於宏任務和微任務以及事件循環可以參考我的另兩篇專欄)
(看到這你就會發現,其實問框架最終還是考驗你的原生JavaScript功底)
5.說一下Vue的生命週期
6.你的接口請求一般放在哪個生命週期中?
7.再說一下Computed和Watch
8.說一下v-if和v-show的區別
9.組件中的data爲什麼是一個函數?
10.說一下v-model的原理
11.Vue事件綁定原理說一下
12.Vue模版編譯原理知道嗎,能簡單說一下嗎?
簡單說,Vue的編譯過程就是將template轉化爲render函數的過程。會經歷以下階段:
生成AST樹
優化
codegen
首先解析模版,生成AST語法樹(一種用JavaScript對象的形式來描述整個模板)。使用大量的正則表達式對模板進行解析,遇到標籤、文本的時候都會執行對應的鉤子進行相關處理。
Vue的數據是響應式的,但其實模板中並不是所有的數據都是響應式的。有一些數據首次渲染後就不會再變化,對應的DOM也不會變化。那麼優化過程就是深度遍歷AST樹,按照相關條件對樹節點進行標記。這些被標記的節點(靜態節點)我們就可以跳過對它們的比對,對運行時的模板起到很大的優化作用。
編譯的最後一步是將優化後的AST樹轉換爲可執行的代碼。
13.Vue2.x和Vue3.x渲染器的diff算法分別說一下
簡單來說,diff算法有以下過程
同級比較,再比較子節點
先判斷一方有子節點一方沒有子節點的情況(如果新的children沒有子節點,將舊的子節點移除)
比較都有子節點的情況(核心diff)
遞歸比較子節點
正常Diff兩個樹的時間複雜度是O(n3),但實際情況下我們很少會進行跨層級的移動DOM,所以Vue將Diff進行了優化,從O(n3) -> O(n),只有當新舊children都爲多個子節點時才需要用核心的Diff算法進行同層級比較。
Vue2的核心Diff算法採用了雙端比較的算法,同時從新舊children的兩端開始進行比較,藉助key值找到可複用的節點,再進行相關操作。相比React的Diff算法,同樣情況下可以減少移動節點次數,減少不必要的性能損耗,更加的優雅。
Vue3.x借鑑了ivi算法和 inferno算法
在創建VNode時就確定其類型,以及在mount/patch的過程中採用位運算來判斷一個VNode的類型,在這個基礎之上再配合核心的Diff算法,使得性能上較Vue2.x有了提升。(實際的實現可以結合Vue3.x源碼看。)
該算法中還運用了動態規劃的思想求解最長遞歸子序列。
(看到這你還會發現,框架內無處不蘊藏着數據結構和算法的魅力)
14.再說一下虛擬Dom以及key屬性的作用
由於在瀏覽器中操作DOM是很昂貴的。頻繁的操作DOM,會產生一定的性能問題。這就是虛擬Dom的產生原因。
Vue2的Virtual DOM借鑑了開源庫snabbdom的實現。
Virtual DOM本質就是用一個原生的JS對象去描述一個DOM節點。是對真實DOM的一層抽象。(也就是源碼中的VNode類,它定義在src/core/vdom/vnode.js中。)
VirtualDOM映射到真實DOM要經歷VNode的create、diff、patch等階段。
「key的作用是儘可能的複用 DOM 元素。」
新舊 children 中的節點只有順序是不同的時候,最佳的操作應該是通過移動元素的位置來達到更新的目的。
需要在新舊 children 的節點中保存映射關係,以便能夠在舊 children 的節點中找到可複用的節點。key也就是children中節點的唯一標識。
15.keep-alive瞭解嗎
keep-alive可以實現組件緩存,當組件切換時不會對當前組件進行卸載。
常用的兩個屬性include/exclude,允許組件有條件的進行緩存。
兩個生命週期activated/deactivated,用來得知當前組件是否處於活躍狀態。
keep-alive的中還運用了LRU(Least Recently Used)算法。
(又是數據結構與算法,原來算法在前端有這麼多的應用)
16.Vue中組件生命週期調用順序說一下
組件的調用順序都是先父後子,渲染完成的順序是先子後父。
組件的銷燬操作是先父後子,銷燬完成的順序是先子後父。
17.Vue2.x組件通信有哪些方式?
父子組件通信
父->子props,子->父 o n 、 on、 on、emit
獲取父子組件實例 p a r e n t 、 parent、 parent、children
Ref 獲取實例的方式調用組件的屬性或者方法
Provide、inject 官方不推薦使用,但是寫組件庫時很常用
兄弟組件通信
Event Bus 實現跨組件通信 Vue.prototype.$bus = new Vue
Vuex
跨級組件通信
Vuex
a t t r s 、 attrs、 attrs、listeners
Provide、inject
18.SSR瞭解嗎?
SSR也就是服務端渲染,也就是將Vue在客戶端把標籤渲染成HTML的工作放在服務端完成,然後再把html直接返回給客戶端。
SSR有着更好的SEO、並且首屏加載速度更快等優點。不過它也有一些缺點,比如我們的開發條件會受到限制,服務器端渲染只支持beforeCreate和created兩個鉤子,當我們需要一些外部擴展庫時需要特殊處理,服務端渲染應用程序也需要處於Node.js的運行環境。還有就是服務器會有更大的負載需求。
19.你都做過哪些Vue的性能優化?
還可以使用緩存(客戶端緩存、服務端緩存)優化、服務端開啓gzip壓縮等。
20.hash路由和history路由實現原理說一下
location.hash的值實際就是URL中#後面的東西。
history實際採用了HTML5中提供的API來實現,主要有history.pushState()和history.replaceState()。