記一次在夢里的大廠面試情景
轉(zhuǎn)自:_楊溜溜 segmentfault.com/a/1190000023949535
前言
來,先介紹一下Vue的響應式系統(tǒng)
computed與watch的區(qū)別
介紹一下Vue的生命周期
beforeCreate:是new Vue()之后觸發(fā)的第一個鉤子,在當前階段data、methods、computed以及watch上的數(shù)據(jù)和方法都不能被訪問。
created:在實例創(chuàng)建完成后發(fā)生,當前階段已經(jīng)完成了數(shù)據(jù)觀測,也就是可以使用數(shù)據(jù),更改數(shù)據(jù),在這里更改數(shù)據(jù)不會觸發(fā)updated函數(shù)。可以做一些初始數(shù)據(jù)的獲取,在當前階段無法與Dom進行交互,如果非要想,可以通過vm.$nextTick來訪問Dom。
beforeMount:發(fā)生在掛載之前,在這之前template模板已導入渲染函數(shù)編譯。而當前階段虛擬Dom已經(jīng)創(chuàng)建完成,即將開始渲染。在此時也可以對數(shù)據(jù)進行更改,不會觸發(fā)updated。
mounted:在掛載完成后發(fā)生,在當前階段,真實的Dom掛載完畢,數(shù)據(jù)完成雙向綁定,可以訪問到Dom節(jié)點,使用$refs屬性對Dom進行操作。
beforeUpdate:發(fā)生在更新之前,也就是響應式數(shù)據(jù)發(fā)生更新,虛擬dom重新渲染之前被觸發(fā),你可以在當前階段進行更改數(shù)據(jù),不會造成重渲染。
updated:發(fā)生在更新完成之后,當前階段組件Dom已完成更新。要注意的是避免在此期間更改數(shù)據(jù),因為這可能會導致無限循環(huán)的更新。
beforeDestroy:發(fā)生在實例銷毀之前,在當前階段實例完全可以被使用,我們可以在這時進行善后收尾工作,比如清除計時器。
destroyed:發(fā)生在實例銷毀之后,這個時候只剩下了dom空殼。組件已被拆解,數(shù)據(jù)綁定被卸除,監(jiān)聽被移出,子實例也統(tǒng)統(tǒng)被銷毀。
為什么組件的data必須是一個函數(shù)
組件之間是怎么通信的
-
父子組件通信
prop
$on/$emit
$parent/$children,$refs.xxx,獲取到實例后直接獲取屬性數(shù)據(jù)或調(diào)用組件方法
-
兄弟組件通信
$on/$emit,可以為兄弟組件的實例之間new一個Vue實例,作為Event Bus進行通信。
-
跨級組件通信
Vue事件綁定原理說一下
$on方法將事件注冊到內(nèi)部,在需要的時候使用$emit觸發(fā)函數(shù),而對于原生native事件,使用addEventListener綁定到真實的DOM元素上。
slot是什么?有什么作用?原理是什么?
-
默認插槽:又名匿名查抄,當slot沒有指定name屬性值的時候一個默認顯示插槽,一個組件內(nèi)只有有一個匿名插槽。 -
具名插槽:帶有具體名字的插槽,也就是帶有name屬性的slot,一個組件可以出現(xiàn)多個具名插槽。 -
作用域插槽:默認插槽、具名插槽的一個變體,可以是匿名插槽,也可以是具名插槽,該插槽的不同點是在子組件渲染作用域插槽時,可以將子組件內(nèi)部的數(shù)據(jù)傳遞給父組件,讓父組件根據(jù)子組件的傳遞過來的數(shù)據(jù)決定如何渲染該插槽。
vm.$slot中,默認插槽為vm.$slot.default,具名插槽為vm.$slot.xxx,xxx 為插槽名,當組件執(zhí)行渲染函數(shù)時候,遇到slot標簽,使用$slot中的內(nèi)容進行替換,此時可以為插槽傳遞數(shù)據(jù),若存在數(shù)據(jù),則可稱該插槽為作用域插槽。
Vue模板渲染的原理是什么?
-
parse階段:使用大量的正則表達式對template字符串進行解析,將標簽、指令、屬性等轉(zhuǎn)化為抽象語法樹AST。 -
optimize階段:遍歷AST,找到其中的一些靜態(tài)節(jié)點并進行標記,方便在頁面重渲染的時候進行diff比較時,直接跳過這一些靜態(tài)節(jié)點,優(yōu)化runtime的性能。 -
generate階段:將最終的AST轉(zhuǎn)化為render函數(shù)字符串。
template預編譯是什么?
render function,這個過程,正好可以在項目構(gòu)建的過程中完成,這樣可以讓實際組件在 runtime 時直接跳過模板渲染,進而提升性能,這個在項目構(gòu)建的編譯template的過程,就是預編譯。
那template和jsx的有什么分別?
vue-loader編譯.vue文件,內(nèi)部依賴的vue-template-compiler模塊,在 webpack 構(gòu)建過程中,將template預編譯成 render 函數(shù)。
babel-plugin-transform-vue-jsx之后,就可以直接手寫render函數(shù)。
說一下什么是Virtual DOM
介紹一下Vue中的Diff算法
-
首先,對比節(jié)點本身,判斷是否為同一節(jié)點,如果不為相同節(jié)點,則刪除該節(jié)點重新創(chuàng)建節(jié)點進行替換 -
如果為相同節(jié)點,進行patchVnode,判斷如何對該節(jié)點的子節(jié)點進行處理,先判斷一方有子節(jié)點一方?jīng)]有子節(jié)點的情況(如果新的children沒有子節(jié)點,將舊的子節(jié)點移除) -
比較如果都有子節(jié)點,則進行updateChildren,判斷如何對這些新老節(jié)點的子節(jié)點進行操作(diff核心)。 -
匹配時,找到相同的子節(jié)點,遞歸比較子節(jié)點
O(n^3)降低值O(n),也就是說,只有當新舊children都為多個子節(jié)點時才需要用核心的Diff算法進行同層級比較。
key屬性的作用是什么
說說Vue2.0和Vue3.0有什么區(qū)別
-
重構(gòu)響應式系統(tǒng),使用Proxy替換Object.defineProperty,使用Proxy優(yōu)勢:
-
可直接監(jiān)聽數(shù)組類型的數(shù)據(jù)變化 -
監(jiān)聽的目標為對象本身,不需要像Object.defineProperty一樣遍歷每個屬性,有一定的性能提升 -
可攔截apply、ownKeys、has等13種方法,而Object.defineProperty不行 -
直接實現(xiàn)對象屬性的新增/刪除 -
新增Composition API,更好的邏輯復用和代碼組織
-
重構(gòu) Virtual DOM
-
模板編譯時的優(yōu)化,將一些靜態(tài)節(jié)點編譯成常量 -
slot優(yōu)化,將slot編譯為lazy函數(shù),將slot的渲染的決定權交給子組件 -
模板中內(nèi)聯(lián)事件的提取并重用(原本每次渲染都重新生成內(nèi)聯(lián)函數(shù)) -
代碼結(jié)構(gòu)調(diào)整,更便于Tree shaking,使得體積更小
-
使用Typescript替換Flow
為什么要新增Composition API,它能解決什么問題
都說Composition API與React Hook很像,說說區(qū)別
-
不能在循環(huán)、條件、嵌套函數(shù)中調(diào)用Hook -
必須確??偸窃谀愕腞eact函數(shù)的頂層調(diào)用Hook -
useEffect、useMemo等函數(shù)必須手動確定依賴關系
-
聲明在setup函數(shù)內(nèi),一次組件實例化只調(diào)用一次setup,而React Hook每次重渲染都需要調(diào)用Hook,使得React的GC比Vue更有壓力,性能也相對于Vue來說也較慢 -
Compositon API的調(diào)用不需要顧慮調(diào)用順序,也可以在循環(huán)、條件、嵌套函數(shù)中使用 -
響應式系統(tǒng)自動實現(xiàn)了依賴收集,進而組件的部分的性能優(yōu)化由Vue內(nèi)部自己完成,而React Hook需要手動傳入依賴,而且必須必須保證依賴的順序,讓useEffect、useMemo等函數(shù)正確的捕獲依賴變量,否則會由于依賴不正確使得組件性能下降。
SSR有了解嗎?原理是什么?
-
有利于SEO:其實就是有利于爬蟲來爬你的頁面,因為部分頁面爬蟲是不支持執(zhí)行JavaScript的,這種不支持執(zhí)行JavaScript的爬蟲抓取到的非SSR的頁面會是一個空的HTML頁面,而有了SSR以后,這些爬蟲就可以獲取到完整的HTML結(jié)構(gòu)的數(shù)據(jù),進而收錄到搜索引擎中。 -
白屏時間更短:相對于客戶端渲染,服務端渲染在瀏覽器請求URL之后已經(jīng)得到了一個帶有數(shù)據(jù)的HTML文本,瀏覽器只需要解析HTML,直接構(gòu)建DOM樹就可以。而客戶端渲染,需要先得到一個空的HTML頁面,這個時候頁面已經(jīng)進入白屏,之后還需要經(jīng)過加載并執(zhí)行 JavaScript、請求后端服務器獲取數(shù)據(jù)、JavaScript 渲染頁面幾個過程才可以看到最后的頁面。特別是在復雜應用中,由于需要加載 JavaScript 腳本,越是復雜的應用,需要加載的 JavaScript 腳本就越多、越大,這會導致應用的首屏加載時間非常長,進而降低了體驗感。
更多詳情查看 徹底理解服務端渲染-SSR原理 https://github.com/yacan8/blog/issues/30
結(jié)束
點個『在看』支持下 ![]()
評論
圖片
表情
