面試必備的13道可以舉一反三的Vue面試題

前言
Vue框架部分我們會涉及一些高頻且有一定探討價值的面試題,我們不會涉及一些非常初級的在官方文檔就能查看的純記憶性質(zhì)的面試題,比如:
- vue常用的修飾符?
- vue-cli 工程常用的 npm 命令有哪些?
- vue中 keep-alive 組件的作用?
首先,上述類型的面試題在文檔中可查,沒有比官方文檔更權(quán)威的答案了,其次這種問題沒有太大價值,除了考察候選人的記憶力,最后,這種面試題只要用過vue的都知道,沒有必要占用我們的篇幅.
我們的問題并不多,但是難度可能會高一些,如果你真的搞懂了這些問題,在絕大多數(shù)情況下會有舉一反三的效果,可以說基本能拿下Vue相關(guān)的所有重要知識點了.
你對MVVM的理解?
MVVM是什么?
MVVM 模式,顧名思義即 Model-View-ViewModel 模式。它萌芽于2005年微軟推出的基于 Windows 的用戶界面框架 WPF ,前端最早的 MVVM 框架 knockout 在2010年發(fā)布。
Model 層: 對應(yīng)數(shù)據(jù)層的域模型,它主要做域模型的同步。通過 Ajax/fetch 等 API 完成客戶端和服務(wù)端業(yè)務(wù) Model 的同步。在層間關(guān)系里,它主要用于抽象出 ViewModel 中視圖的 Model。
View 層:作為視圖模板存在,在 MVVM 里,整個 View 是一個動態(tài)模板。除了定義結(jié)構(gòu)、布局外,它展示的是 ViewModel 層的數(shù)據(jù)和狀態(tài)。View 層不負(fù)責(zé)處理狀態(tài),View 層做的是 數(shù)據(jù)綁定的聲明、 指令的聲明、 事件綁定的聲明。
ViewModel 層:把 View 需要的層數(shù)據(jù)暴露,并對 View 層的 數(shù)據(jù)綁定聲明、 指令聲明、 事件綁定聲明 負(fù)責(zé),也就是處理 View 層的具體業(yè)務(wù)邏輯。ViewModel 底層會做好綁定屬性的監(jiān)聽。當(dāng) ViewModel 中數(shù)據(jù)變化,View 層會得到更新;而當(dāng) View 中聲明了數(shù)據(jù)的雙向綁定(通常是表單元素),框架也會監(jiān)聽 View 層(表單)值的變化。一旦值變化,View 層綁定的 ViewModel 中的數(shù)據(jù)也會得到自動更新。
MVVM的優(yōu)缺點?
優(yōu)點:
- 分離視圖(View)和模型(Model),降低代碼耦合,提高視圖或者邏輯的重用性: 比如視圖(View)可以獨(dú)立于Model變化和修改,一個ViewModel可以綁定不同的"View"上,當(dāng)View變化的時候Model不可以不變,當(dāng)Model變化的時候View也可以不變。你可以把一些視圖邏輯放在一個ViewModel里面,讓很多view重用這段視圖邏輯
- 提高可測試性: ViewModel的存在可以幫助開發(fā)者更好地編寫測試代碼
- 自動更新dom: 利用雙向綁定,數(shù)據(jù)更新后視圖自動更新,讓開發(fā)者從繁瑣的手動dom中解放
缺點:
- Bug很難被調(diào)試: 因為使用雙向綁定的模式,當(dāng)你看到界面異常了,有可能是你View的代碼有Bug,也可能是Model的代碼有問題。數(shù)據(jù)綁定使得一個位置的Bug被快速傳遞到別的位置,要定位原始出問題的地方就變得不那么容易了。另外,數(shù)據(jù)綁定的聲明是指令式地寫在View的模版當(dāng)中的,這些內(nèi)容是沒辦法去打斷點debug的
- 一個大的模塊中model也會很大,雖然使用方便了也很容易保證了數(shù)據(jù)的一致性,當(dāng)時長期持有,不釋放內(nèi)存就造成了花費(fèi)更多的內(nèi)存
- 對于大型的圖形應(yīng)用程序,視圖狀態(tài)較多,ViewModel的構(gòu)建和維護(hù)的成本都會比較高
你對Vue生命周期的理解?
生命周期是什么
Vue 實例有一個完整的生命周期,也就是從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模版、掛載Dom -> 渲染、更新 -> 渲染、卸載等一系列過程,我們稱這是Vue的生命周期。
各個生命周期的作用
生命周期 | 描述 |
---|---|
beforeCreate | 組件實例被創(chuàng)建之初,組件的屬性生效之前 |
created | 組件實例已經(jīng)完全創(chuàng)建,屬性也綁定,但真實dom還沒有生成, $el 還不可用 |
beforeMount | 在掛載開始之前被調(diào)用:相關(guān)的 render 函數(shù)首次被調(diào)用 |
mounted | el 被新創(chuàng)建的 vm.$el 替換,并掛載到實例上去之后調(diào)用該鉤子 |
beforeUpdate | 組件數(shù)據(jù)更新之前調(diào)用,發(fā)生在虛擬 DOM 打補(bǔ)丁之前 |
update | 組件數(shù)據(jù)更新之后 |
activited | keep-alive專屬,組件被激活時調(diào)用 |
deadctivated | keep-alive專屬,組件被銷毀時調(diào)用 |
beforeDestory | 組件銷毀前調(diào)用 |
destoryed | 組件銷毀后調(diào)用 |
生命周期示意圖
異步請求適合在哪個生命周期調(diào)用?
官方實例的異步請求是在mounted生命周期中調(diào)用的,而實際上也可以在created生命周期中調(diào)用。
Vue組件如何通信?
Vue組件通信的方法如下:
- props/$emit+v-on : 通過props將數(shù)據(jù)自上而下傳遞,而通過$emit和v-on來向上傳遞信息。
- EventBus: 通過EventBus進(jìn)行信息的發(fā)布與訂閱
- vuex: 是全局?jǐn)?shù)據(jù)管理庫,可以通過vuex管理全局的數(shù)據(jù)流
- $attrs/$listeners : Vue2.4中加入的 $attrs/$listeners 可以進(jìn)行跨級的組件通信
- provide/inject:以允許一個祖先組件向其所有子孫后代注入一個依賴,不論組件層次有多深,并在起上下游關(guān)系成立的時間里始終生效,這成為了跨組件通信的基礎(chǔ)
還有一些用solt插槽或者ref實例進(jìn)行通信的,使用場景過于有限就不贅述了。
computed和watch有什么區(qū)別?
computed:
- computed是計算屬性,也就是計算值,它更多用于計算值的場景
- computed具有緩存性,computed的值在getter執(zhí)行后是會緩存的,只有在它依賴的屬性值改變之后,下一次獲取computed的值時才會重新調(diào)用對應(yīng)的getter來計算
- computed適用于計算比較消耗性能的計算場景
watch:
- 更多的是「觀察」的作用,類似于某些數(shù)據(jù)的監(jiān)聽回調(diào),用于觀察props $emit或者本組件的值,當(dāng)數(shù)據(jù)變化時來執(zhí)行回調(diào)進(jìn)行后續(xù)操作
- 無緩存性,頁面重新渲染時值不變化也會執(zhí)行
小結(jié):
- 當(dāng)我們要進(jìn)行數(shù)值計算,而且依賴于其他數(shù)據(jù),那么把這個數(shù)據(jù)設(shè)計為computed
- 如果你需要在某個數(shù)據(jù)變化時做一些事情,使用watch來觀察這個數(shù)據(jù)變化
Vue是如何實現(xiàn)雙向綁定的?
利用 Object.defineProperty
劫持對象的訪問器,在屬性值發(fā)生變化時我們可以獲取變化,然后根據(jù)變化進(jìn)行后續(xù)響應(yīng),在vue3.0中通過Proxy代理對象進(jìn)行類似的操作。
// 這是將要被劫持的對象 const data = { name: '', }; function say(name) { if (name === '古天樂') { console.log('給大家推薦一款超好玩的游戲'); } else if (name === '渣渣輝') { console.log('戲我演過很多,可游戲我只玩貪玩懶月'); } else { console.log('來做我的兄弟'); } } // 遍歷對象,對其屬性值進(jìn)行劫持 Object.keys(data).forEach(function(key) { Object.defineProperty(data, key, { enumerable: true, configurable: true, get: function() { console.log('get'); }, set: function(newVal) { // 當(dāng)屬性值發(fā)生變化時我們可以進(jìn)行額外操作 console.log(`大家好,我系${newVal}`); say(newVal); }, }); }); data.name = '渣渣輝'; //大家好,我系渣渣輝 //戲我演過很多,可游戲我只玩貪玩懶月
Proxy與Object.defineProperty的優(yōu)劣對比?
Proxy的優(yōu)勢如下:
- Proxy可以直接監(jiān)聽對象而非屬性
- Proxy可以直接監(jiān)聽數(shù)組的變化
- Proxy有多達(dá)13種攔截方法,不限于apply、ownKeys、deleteProperty、has等等是Object.defineProperty不具備的
- Proxy返回的是一個新對象,我們可以只操作新的對象達(dá)到目的,而Object.defineProperty只能遍歷對象屬性直接修改
- Proxy作為新標(biāo)準(zhǔn)將受到瀏覽器廠商重點持續(xù)的性能優(yōu)化,也就是傳說中的新標(biāo)準(zhǔn)的性能紅利
Object.defineProperty的優(yōu)勢如下:
兼容性好,支持IE9
你是如何理解Vue的響應(yīng)式系統(tǒng)的?
響應(yīng)式系統(tǒng)簡述:
- 任何一個 Vue Component 都有一個與之對應(yīng)的 Watcher 實例。
- Vue 的 data 上的屬性會被添加 getter 和 setter 屬性。
- 當(dāng) Vue Component render 函數(shù)被執(zhí)行的時候, data 上會被 觸碰(touch), 即被讀, getter 方法會被調(diào)用, 此時 Vue 會去記錄此 Vue component 所依賴的所有 data。(這一過程被稱為依賴收集)
- data 被改動時(主要是用戶操作), 即被寫, setter 方法會被調(diào)用, 此時 Vue 會去通知所有依賴于此 data 的組件去調(diào)用他們的 render 函數(shù)進(jìn)行更新。
虛擬DOM的優(yōu)劣如何?
優(yōu)點:
- 保證性能下限: 虛擬DOM可以經(jīng)過diff找出最小差異,然后批量進(jìn)行patch,這種操作雖然比不上手動優(yōu)化,但是比起粗暴的DOM操作性能要好很多,因此虛擬DOM可以保證性能下限
- 無需手動操作DOM: 虛擬DOM的diff和patch都是在一次更新中自動進(jìn)行的,我們無需手動操作DOM,極大提高開發(fā)效率
- 跨平臺: 虛擬DOM本質(zhì)上是JavaScript對象,而DOM與平臺強(qiáng)相關(guān),相比之下虛擬DOM可以進(jìn)行更方便地跨平臺操作,例如服務(wù)器渲染、移動端開發(fā)等等
缺點:
無法進(jìn)行極致優(yōu)化: 在一些性能要求極高的應(yīng)用中虛擬DOM無法進(jìn)行針對性的極致優(yōu)化,比如VScode采用直接手動操作DOM的方式進(jìn)行極端的性能優(yōu)化
虛擬DOM實現(xiàn)原理?
虛擬DOM本質(zhì)上是JavaScript對象,是對真實DOM的抽象
狀態(tài)變更時,記錄新樹和舊樹的差異
最后把差異更新到真正的dom中
詳細(xì)實現(xiàn)見虛擬DOM原理?
既然Vue通過數(shù)據(jù)劫持可以精準(zhǔn)探測數(shù)據(jù)變化,為什么還需要虛擬DOM進(jìn)行diff檢測差異?
考點: Vue的變化偵測原理
前置知識: 依賴收集、虛擬DOM、響應(yīng)式系統(tǒng)
現(xiàn)代前端框架有兩種方式偵測變化,一種是pull一種是push
pull: 其代表為React,我們可以回憶一下React是如何偵測到變化的,我們通常會用 setState
API顯式更新,然后React會進(jìn)行一層層的Virtual Dom Diff操作找出差異,然后Patch到DOM上,React從一開始就不知道到底是哪發(fā)生了變化,只是知道「有變化了」,然后再進(jìn)行比較暴力的Diff操作查找「哪發(fā)生變化了」,另外一個代表就是Angular的臟檢查操作。
push: Vue的響應(yīng)式系統(tǒng)則是push的代表,當(dāng)Vue程序初始化的時候就會對數(shù)據(jù)data進(jìn)行依賴的收集,一但數(shù)據(jù)發(fā)生變化,響應(yīng)式系統(tǒng)就會立刻得知,因此Vue是一開始就知道是「在哪發(fā)生變化了」,但是這又會產(chǎn)生一個問題,如果你熟悉Vue的響應(yīng)式系統(tǒng)就知道,通常一個綁定一個數(shù)據(jù)就需要一個Watcher,一但我們的綁定細(xì)粒度過高就會產(chǎn)生大量的Watcher,這會帶來內(nèi)存以及依賴追蹤的開銷,而細(xì)粒度過低會無法精準(zhǔn)偵測變化,因此Vue的設(shè)計是選擇中等細(xì)粒度的方案,在組件級別進(jìn)行push偵測的方式,也就是那套響應(yīng)式系統(tǒng),通常我們會第一時間偵測到發(fā)生變化的組件,然后在組件內(nèi)部進(jìn)行Virtual Dom Diff獲取更加具體的差異,而Virtual Dom Diff則是pull操作,Vue是push+pull結(jié)合的方式進(jìn)行變化偵測的.
Vue為什么沒有類似于React中shouldComponentUpdate的生命周期?
考點: Vue的變化偵測原理
前置知識: 依賴收集、虛擬DOM、響應(yīng)式系統(tǒng)
根本原因是Vue與React的變化偵測方式有所不同
React是pull的方式偵測變化,當(dāng)React知道發(fā)生變化后,會使用Virtual Dom Diff進(jìn)行差異檢測,但是很多組件實際上是肯定不會發(fā)生變化的,這個時候需要用shouldComponentUpdate進(jìn)行手動操作來減少diff,從而提高程序整體的性能.
Vue是pull+push的方式偵測變化的,在一開始就知道那個組件發(fā)生了變化,因此在push的階段并不需要手動控制diff,而組件內(nèi)部采用的diff方式實際上是可以引入類似于shouldComponentUpdate相關(guān)生命周期的,但是通常合理大小的組件不會有過量的diff,手動優(yōu)化的價值有限,因此目前Vue并沒有考慮引入shouldComponentUpdate這種手動優(yōu)化的生命周期.
Vue中的key到底有什么用?
key
是為Vue中的vnode標(biāo)記的唯一id,通過這個key,我們的diff操作可以更準(zhǔn)確、更快速
diff算法的過程中,先會進(jìn)行新舊節(jié)點的首尾交叉對比,當(dāng)無法匹配的時候會用新節(jié)點的 key
與舊節(jié)點進(jìn)行比對,然后超出差異.
diff程可以概括為:oldCh和newCh各有兩個頭尾的變量StartIdx和EndIdx,它們的2個變量相互比較,一共有4種比較方式。如果4種比較都沒匹配,如果設(shè)置了key,就會用key進(jìn)行比較,在比較的過程中,變量會往中間靠,一旦StartIdx>EndIdx表明oldCh和newCh至少有一個已經(jīng)遍歷完了,就會結(jié)束比較,這四種比較方式就是首、尾、舊尾新頭、舊頭新尾.
- 準(zhǔn)確: 如果不加key,那么vue會選擇復(fù)用節(jié)點(Vue的就地更新策略),導(dǎo)致之前節(jié)點的狀態(tài)被保留下來,會產(chǎn)生一系列的bug.
- 快速: key的唯一性可以被Map數(shù)據(jù)結(jié)構(gòu)充分利用,相比于遍歷查找的時間復(fù)雜度O(n),Map的時間復(fù)雜度僅僅為O(1).
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
- 這篇文章主要介紹了關(guān)于VUE的面試題(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-16
- 這篇文章主要介紹了Vue.js的高級面試題(附答案),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2020-01-13
- 這篇文章主要介紹了12道vue高頻原理面試題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-12-27
- 這篇文章主要介紹了Vuex面試題匯總(推薦),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-15
- 這篇文章主要介紹了web前端面試中關(guān)于VUE的面試題(含答案),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來2019-11-08
- 這篇文章主要介紹了Vue面試題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-07-01
- 這篇文章主要介紹了Vue 高頻基礎(chǔ)面試題,在前端面試中經(jīng)常會遇到,今天小編特意整理分享到腳本之家平臺,需要的朋友可以參考下2020-02-12