這次跟大家分享一些關於Vue的常見面試題,帶你梳理基礎知識,增強Vue知識儲備,值得收藏,快來看看吧!
分享的是一些Vue的常見面試題,是不代表全部。如果文章有不對的地方歡迎指出,有疑惑 或有其他面試題的小夥伴也可以在留言區留言分享,大家一起交流探討,謝謝!
父子元件通訊:props
和 event
、v-
model
、 .sync
、 ref
#、 $parent
和
$children
。 (學習視訊分享:vue視訊教學)
非父子元件通訊:$attr
和$listeners
、
provide
和inject
、eventbus
、透過根實例$root
存取、vuex
、dispatch
和
brodcast
vue 2.0v-model
是⽤來在表單控制項或元件上建立雙向綁定的,他
的本質是 v-bind
和 v-on
的語法糖,在
⼀個元件上使⽤ v-model
,預設會為元件綁定名為 value
的
prop
和名為 input
的事件。
Vue3.0
在 3.x 中,⾃定義元件上的 v-model
相當於傳遞了 modelValue
prop
並接收拋出的update:modelValue
事件
Vuex和全域物件主要有兩種差異:
#Vuex 的狀態儲存是響應式的。當 Vue 元件從 store 讀取狀態的時候,若 store 中的狀態發⽣變 化,那麼對應的組件也會相應地得到⾼效更新。
不能直接改變 store 中的狀態。改變 store 中的狀態的唯⼀途徑就是顯式地提交 (commit)mutation。這樣使得我們可以⽅便地追蹤每⼀個狀態的變化,從⽽讓我們能夠實現⼀些⼯ 具幫助我們更了解我們的應⽤。
渲染過程:⽗元件掛載完成⼀定是等⼦元件都掛載完成後,才算是⽗元件 掛載完,所以⽗組件的mounted在⼦組件mouted之後
⽗beforeCreate -> ⽗created -> ⽗beforeMount -> ⼦beforeCreate -> ⼦created -> ⼦beforeMount -> ⼦mounted -> ⽗mounted
⼦元件更新過程:
⽗元件更新過程:
銷毀過程:⽗beforeDestroy -> ⼦beforeDestroy -> ⼦ destroyed -> ⽗destroyed
看起來很多好像很難記憶,其實只要理解了,不管是哪種情況,都⼀定是⽗組件等待⼦組件完 成後,才會執⾏⾃⼰對應完成的鉤⼦,就可以很容易記住
v-if
會在切換過程中對條件區塊的事件監聽器和⼦元件進⾏銷毀和重建# ,如果初始條件是false,則什麼都不做,直到條件第⼀次為true時才開始。
染模組。
v-show
只是基於css進⾏切換,不管初始條件是
什麼,都會渲染。
所以, v-if
切換的開銷更⼤,⽽ v-show
初始化渲染開銷更
⼤,在需要頻繁切換,或切換的部分dom很複雜時,讓⽤ v-show
更合
適。渲染後很少切換的則使⽤ v-if
更合適。
在⽹站上動態渲染任意HTML,很容易導致XSS 攻擊。所以只能在可信內 容上使⽤ v-html,且永遠不能⽤於⽤戶提交的內容上。
key
是給每個 vnode
指定的唯有⼀ id
,在同
在等級的 vnode
diff 過程中,可以根據 key
快速的對⽐,來判斷是
否為相同節點,且利⽤ key
的唯⼀性可以⽣成 map
來更快的獲
取相應的節點。
另外指定 key
後,就不再採⽤「就地復⽤」策略了,可以保證渲染的準確性
。
v-for
和v-if
處於同⼀個節點時, v-
for
的優先權⽐ v-if
更⾼,這表示 v-if
將分別重複
運⾏於每個 v-for
迴圈中。如果要遍歷的陣列很⼤,⽽真正要展示的資料很少時
,這將造成很⼤的效能浪費。 computed
,先對資料進⾏過濾。 區別:
url 展示上,hash 模式有"#",history 模式沒有
## 後⾯ hash 值的變化,不會導致瀏覽器向伺服器發出請求,瀏覽器不發出請
求,就不會刷新⻚⾯。同時透過監聽 hashchange 事件可以知道 hash 發⽣了哪些變化,然後根據
hash 變更來實現更新⻚⾯部分內容的操作。
pushState# 和
replaceState ,這兩個 API 可以在改變 url,但不會發送請求。這樣就可以監
聽聽 url 變化來實現更新⻚⾯部分內容的操作。
縮寫,也就是把
MVC 中
的
Controller 演變成
ViewModel 。
流程總結如下:
1、當元件初始化的時候,computed 和
data 會分別建⽴各
⾃的回應系統,
Observer 遍歷
data中每個屬性設定
get/set 資料攔截
computed 會調⽤
initComputed 函數
註冊⼀個
調⽤ watcher.depend()
⽅法向⾃身的消息訂閱器
dep
的subs
中加入其他屬性的watcher
調⽤ watcher
的evaluate
⽅法(進⽽調⽤
watcher
的get
⽅法)讓⾃身成為其他watcher
的訊息訂閱器的訂閱者,⾸先將watcher
賦給Dep.target
,然
後執⾏ getter
求值函數,當訪問求值函數⾥⾯的屬性(⽐如來⾃
data
、 props
或其他 computed
)時,
會同樣觸發它們的get
存取器函數從⽽將該計算屬性的watcher
加入到求值函數中屬性的watcher
的訊息訂閱器dep
中,當這些
操作完成,最後關閉 Dep.target
賦為 null
並
傳回求值函數結果。
3、當某個屬性發⽣變化,觸發 set
攔截函數,然後調⽤⾃身訊息訂閱器
dep
的 notify
⽅法,遍
歷當前 dep 中保存著所有訂閱者 wathcer
的 subs
數組,並逐個
調⽤ watcher
的 update
⽅
法,完成響應更新。
如果⾯試被問到這個問題,⼜描述不清楚,可以直接畫出Vue 官⽅⽂檔的這個圖,對著圖來 解釋效果會更好。
Object.defineProperty
對資料進⾏劫持,並結合觀察者模式實現。 Object.defineProperty
建立⼀個 observe
來
劫持監聽所有的屬性,把這些屬性全部轉為 getter
和 setter
。 watcher
實例,它會在元件渲染的過
程中把使⽤過的
資料屬性透過 getter
收集為依賴。之後當依賴項的 setter
觸發
時,會通知 watcher
,從⽽使它關聯的元件重新渲染。 Object.defineProperty
只能劫持物件的屬性,⽽ Proxy
是直接代理對象由於
Object.defineProperty
只能對屬性進⾏劫持,需要遍歷物件的每個屬性。 ⽽
Proxy 可以直接代理物件。
Object.defineProperty
對新增屬性需要⼿動進⾏
Observe
, 由於Object.defineProperty
劫持的是物件的屬性,
所以新增屬性時,需要重新遍歷對象,對其新
增屬性再使⽤ Object.defineProperty
進⾏劫持。也正是因為這個原因,使⽤
Vue 給 data
中的陣列或物件新增屬性時,需要讓⽤ vm.$set
才能
保證新增的屬性也是響應式的。
Proxy
⽀持13種攔截操作,這是
defineProperty
所不具有的。
新標準性能紅利Proxy 作為新標準,⻓遠來看,JS引擎會繼續優化
Proxy
,但 getter
和 setter
基本上不會再有針對
性優化。
Proxy
相容性差 ⽬前並沒有⼀個完整⽀持 Proxy
所
有攔截⽅法的Polyfill⽅案
Vue 的 Observer
對陣列做了單獨的處理,對陣列的⽅法進⾏編譯,並賦值給
數組屬性的 __proto__
屬性上,因為原型鏈的機制,找到對應
的⽅法就不會繼續往上找了。編譯⽅法中會對⼀些會增加索引的⽅法( push
,
unshift
, splice
)進⾏⼿動 observe。
能回答清楚這道問題的前提,是清楚 EventLoop 過程。
nextTick
對於 micro task 的實現,會先偵測是否⽀持
Promise
,不⽀持的話,直接指向 macrotask,⽽ macro task 的實現,優先檢
測是否⽀持 setImmediate
(⾼版本IE和Etage⽀持),不⽀持的再去檢測是否⽀
持MessageChannel,如果仍不⽀持,最終降級為setTimeout
0;v-on
)。 注意:之所以將 nextTick
的回呼函數放⼊到陣列中⼀次
性執⾏,⽽不是直接在 nextTick
中執⾏回呼函數,是為了保證在同⼀個tick內多
次執⾏了 nextTcik
,不會開啟多個非同步任務,⽽是把這些非同步任務都壓成⼀個同
步任務,在下⼀個tick內執⾏完畢。
vue模板的編譯過程分為3個階段:
將模板字串解析⽣成AST,⽣成的AST 元素節點總共有3 種類型,1 為普通元素, 2 為 表達式,3為純⽂本。
Vue 模板中並不是所有資料都是響應式的,有很多資料是⾸次渲染後就永遠不會變化的,那麼 這部分資料⽣成的 DOM 也不會變化,我們可以在 patch 的過程跳過對他們的⽐對。
此階段會深度遍歷⽣成的 AST 樹,偵測它的每⼀顆⼦樹是不是靜態節點,如果是靜態節點則 它們⽣成DOM 永遠不需要改變,這對運⾏時對模板的更新起到極⼤的優化作⽤。
1、⽣成代碼
const code = generate(ast, options)
透過 generate ⽅法,將ast⽣成 render 函數。
Vue3.x改⽤ Proxy
取代Object.defineProperty。因為Proxy可以直接監聽對
象和數組的變化,並且有多達13種攔截⽅法。並且作為新標準將受到瀏覽器⼚商重點持續的性能優
化。
Proxy只會代理物件的第⼀層,那麼Vue3⼜是怎麼處理這個問題的呢?
判斷當前Reflect.get的回傳值是否為Object,如果是則再透過 reactive ⽅法做代理, 這 樣就實現了深度觀測。
監控數組的時候可能觸發多次get/set,那麼如何防⽌觸發多次呢?
我們可以判斷key是否為目前被代理物件target⾃身屬性,也可以判斷舊值與新值是否相等, 只有滿足以上兩個條件之⼀時,才有可能執⾏trigger。
編碼階段
##SEO優化
##打包最佳化
#使用者體驗
以上是【整理分享】一些Vue高頻面試題的詳細內容。更多資訊請關注PHP中文網其他相關文章!