小編給大家分享一下Vue相關面試題有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
創新互聯于2013年開始,是專業互聯網技術服務公司,擁有項目成都網站設計、網站制作網站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元南召做網站,已為上家服務,為南召各地企業和個人服務,聯系電話:18980820575
MVVM是Model-View-ViewModel
縮寫,也就是把MVC
中的Controller
演變成ViewModel
。Model層代表數據模型,View代表UI組件,ViewModel是View和Model層的橋梁,數據會綁定到viewModel層并自動將數據渲染到頁面中,視圖變化的時候會通知viewModel層更新數據。
Vue在初始化數據時,會使用Object.defineProperty
重新定義data中的所有屬性,當頁面使用對應屬性時,首先會進行依賴收集(收集當前組件的watcher
)如果屬性發生變化會通知相關依賴進行更新操作(發布訂閱
)。
(還好我有看,這個難不倒我)
Vue3.x改用Proxy
替代Object.defineProperty。因為Proxy可以直接監聽對象和數組的變化,并且有多達13種攔截方法。并且作為新標準將受到瀏覽器廠商重點持續的性能優化。
Proxy只會代理對象的第一層,那么Vue3又是怎樣處理這個問題的呢?
(很簡單啊)
判斷當前Reflect.get的返回值是否為Object,如果是則再通過reactive
方法做代理,
這樣就實現了深度觀測。
監測數組的時候可能觸發多次get/set,那么如何防止觸發多次呢?
我們可以判斷key是否為當前被代理對象target自身屬性,也可以判斷舊值與新值是否相等,只有滿足以上兩個條件之一時,才有可能執行trigger。
面試官抬起了頭。心里暗想
(這小子還行,比上兩個強,應該是多多少少看過Vue3的源碼了)
使用了函數劫持的方式,重寫了數組的方法,Vue將data中的數組進行了原型鏈重寫,指向了自己定義的數組原型方法。這樣當調用數組api時,可以通知依賴更新。如果數組中包含著引用類型,會對數組中的引用類型再次遞歸遍歷進行監控。這樣就實現了監測數組變化。
(能問到這的面試官都比較注重深度,這些常規操作要記牢)
(原型鏈的細節可以參考我的另一篇專欄)
一文帶你徹底搞懂JavaScript原型鏈
在下次 DOM 更新循環結束之后執行延遲回調。nextTick主要使用了宏任務和微任務。根據執行環境分別嘗試采用
Promise
MutationObserver
setImmediate
如果以上都不行則采用setTimeout
定義了一個異步方法,多次調用nextTick會將方法存入隊列中,通過這個異步方法清空當前隊列。
(關于宏任務和微任務以及事件循環可以參考我的另兩篇專欄)
(看到這你就會發現,其實問框架最終還是考驗你的原生JavaScript功底)
瀏覽器中JavaScript的事件循環
Node.js事件循環
beforeCreate
是new Vue()之后觸發的第一個鉤子,在當前階段data、methods、computed以及watch上的數據和方法都不能被訪問。
created
在實例創建完成后發生,當前階段已經完成了數據觀測,也就是可以使用數據,更改數據,在這里更改數據不會觸發updated函數。可以做一些初始數據的獲取,在當前階段無法與Dom進行交互,如果非要想,可以通過vm.$nextTick來訪問Dom。
beforeMount
發生在掛載之前,在這之前template模板已導入渲染函數編譯。而當前階段虛擬Dom已經創建完成,即將開始渲染。在此時也可以對數據進行更改,不會觸發updated。
mounted
在掛載完成后發生,在當前階段,真實的Dom掛載完畢,數據完成雙向綁定,可以訪問到Dom節點,使用$refs屬性對Dom進行操作。
beforeUpdate
發生在更新之前,也就是響應式數據發生更新,虛擬dom重新渲染之前被觸發,你可以在當前階段進行更改數據,不會造成重渲染。
updated
發生在更新完成之后,當前階段組件Dom已完成更新。要注意的是避免在此期間更改數據,因為這可能會導致無限循環的更新。
beforeDestroy
發生在實例銷毀之前,在當前階段實例完全可以被使用,我們可以在這時進行善后收尾工作,比如清除計時器。
destroyed
發生在實例銷毀之后,這個時候只剩下了dom空殼。組件已被拆解,數據綁定被卸除,監聽被移出,子實例也統統被銷毀。
(關于Vue的生命周期詳解感興趣的也請移步我的另一篇專欄)
從源碼解讀Vue生命周期,讓面試官對你刮目相看
接口請求一般放在mounted
中,但需要注意的是服務端渲染時不支持mounted,需要放到created
中。
Computed
本質是一個具備緩存的watcher,依賴的屬性發生變化就會更新視圖。
適用于計算比較消耗性能的計算場景。當表達式過于復雜時,在模板中放入過多邏輯會讓模板難以維護,可以將復雜的邏輯放入計算屬性中處理。
Watch
沒有緩存性,更多的是觀察的作用,可以監聽某些數據執行回調。當我們需要深度監聽對象中的屬性時,可以打開deep:true
選項,這樣便會對對象中的每一項進行監聽。這樣會帶來性能問題,優化的話可以使用字符串形式
監聽,如果沒有寫到組件中,不要忘記使用unWatch手動注銷
哦。
當條件不成立時,v-if
不會渲染DOM元素,v-show
操作的是樣式(display),切換當前DOM的顯示和隱藏。
一個組件被復用多次的話,也就會創建多個實例。本質上,這些實例用的都是同一個構造函數
。如果data是對象的話,對象屬于引用類型,會影響到所有的實例。所以為了保證組件不同的實例之間data不沖突,data必須是一個函數。
v-model
本質就是一個語法糖,可以看成是value + input
方法的語法糖。
可以通過model屬性的prop
和event
屬性來進行自定義。原生的v-model,會根據標簽的不同生成不同的事件和屬性。
原生事件綁定是通過addEventListener
綁定給真實元素的,組件事件綁定是通過Vue自定義的$on
實現的。
面試官:(這小子基礎還可以,接下來我得上上難度了)
簡單說,Vue的編譯過程就是將template
轉化為render
函數的過程。會經歷以下階段:
生成AST樹
優化
codegen
首先解析模版,生成AST語法樹
(一種用JavaScript對象的形式來描述整個模板)。
使用大量的正則表達式對模板進行解析,遇到標簽、文本的時候都會執行對應的鉤子進行相關處理。
Vue的數據是響應式的,但其實模板中并不是所有的數據都是響應式的。有一些數據首次渲染后就不會再變化,對應的DOM也不會變化。那么優化過程就是深度遍歷AST樹,按照相關條件對樹節點進行標記。這些被標記的節點(靜態節點)我們就可以跳過對它們的比對
,對運行時的模板起到很大的優化作用。
編譯的最后一步是將優化后的AST樹轉換為可執行的代碼
。
面試官:(精神小伙啊,有點東西,難度提升,不信難不倒你)
簡單來說,diff算法有以下過程
同級比較,再比較子節點
先判斷一方有子節點一方沒有子節點的情況(如果新的children沒有子節點,將舊的子節點移除)
比較都有子節點的情況(核心diff)
遞歸比較子節點
正常Diff兩個樹的時間復雜度是O(n^3)
,但實際情況下我們很少會進行跨層級的移動DOM
,所以Vue將Diff進行了優化,從O(n^3) -> O(n)
,只有當新舊children都為多個子節點時才需要用核心的Diff算法進行同層級比較。
Vue2的核心Diff算法采用了雙端比較
的算法,同時從新舊children的兩端開始進行比較,借助key值找到可復用的節點,再進行相關操作。相比React的Diff算法,同樣情況下可以減少移動節點次數,減少不必要的性能損耗,更加的優雅。
Vue3.x借鑒了
ivi算法和 inferno算法
在創建VNode時就確定其類型,以及在 mount/patch
的過程中采用位運算
來判斷一個VNode的類型,在這個基礎之上再配合核心的Diff算法,使得性能上較Vue2.x有了提升。(實際的實現可以結合Vue3.x源碼看。)
該算法中還運用了動態規劃
的思想求解最長遞歸子序列。
(看到這你還會發現,框架內無處不蘊藏著數據結構和算法的魅力)
面試官:(可以可以,看來是個苗子,不過自我介紹屬實有些無聊,下一題)
(基操,勿6)
由于在瀏覽器中操作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中節點的唯一標識。
keep-alive
可以實現組件緩存,當組件切換時不會對當前組件進行卸載。
常用的兩個屬性include/exclude
,允許組件有條件的進行緩存。
兩個生命周期activated/deactivated
,用來得知當前組件是否處于活躍狀態。
keep-alive的中還運用了LRU(Least Recently Used)
算法。
(又是數據結構與算法,原來算法在前端也有這么多的應用)
組件的調用順序都是先父后子
,渲染完成的順序是先子后父
。
組件的銷毀操作是先父后子
,銷毀完成的順序是先子后父
。
加載渲染過程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted
子組件更新過程
父beforeUpdate->子beforeUpdate->子updated->父updated
父組件更新過程
父 beforeUpdate -> 父 updated
銷毀過程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
父子組件通信
父->子props
,子->父 $on、$emit
獲取父子組件實例 $parent、$children
Ref
獲取實例的方式調用組件的屬性或者方法
Provide、inject
官方不推薦使用,但是寫組件庫時很常用
兄弟組件通信
Event Bus
實現跨組件通信 Vue.prototype.$bus = new Vue
Vuex
跨級組件通信
Vuex
$attrs、$listeners
Provide、inject
SSR也就是服務端渲染,也就是將Vue在客戶端把標簽渲染成HTML的工作放在服務端完成,然后再把html直接返回給客戶端
。
SSR有著更好的SEO、并且首屏加載速度更快等優點。不過它也有一些缺點,比如我們的開發條件會受到限制,服務器端渲染只支持beforeCreate
和created
兩個鉤子,當我們需要一些外部擴展庫時需要特殊處理,服務端渲染應用程序也需要處于Node.js的運行環境。還有就是服務器會有更大的負載需求。
編碼階段
盡量減少data中的數據,data中的數據都會增加getter和setter,會收集對應的watcher
v-if和v-for不能連用
如果需要使用v-for給每項元素綁定事件時使用事件代理
SPA 頁面采用keep-alive緩存組件
在更多的情況下,使用v-if替代v-show
key保證唯一
使用路由懶加載、異步組件
防抖、節流
第三方模塊按需導入
長列表滾動到可視區域動態加載
圖片懶加載
SEO優化
預渲染
服務端渲染SSR
打包優化
壓縮代碼
Tree Shaking/Scope Hoisting
使用cdn加載第三方模塊
多線程打包happypack
splitChunks抽離公共文件
sourceMap優化
用戶體驗
骨架屏
PWA
還可以使用緩存(客戶端緩存、服務端緩存)優化、服務端開啟gzip壓縮等。
(優化是個大工程,會涉及很多方面,這里申請另開一個專欄)
location.hash
的值實際就是URL中#
后面的東西。
history實際采用了HTML5中提供的API來實現,主要有history.pushState()
和history.replaceState()
。
以上是“Vue相關面試題有哪些”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注創新互聯行業資訊頻道!
網站名稱:Vue相關面試題有哪些
文章地址:http://vcdvsql.cn/article28/pdsjjp.html
成都網站建設公司_創新互聯,為您提供網站內鏈、響應式網站、網站排名、用戶體驗、品牌網站制作、網站維護
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯