【前端芝士樹】Vue.js面試題整理 / 知識點梳理
【前端芝士樹】 Vue.js 面試題整理
MVVM是什麼?
MVVM 是 Model-View-ViewModel 的縮寫。
-
Model
代表資料模型,也可以在Model中定義資料修改和操作的業務邏輯。 -
View
代表UI 元件,它負責將資料模型轉化成UI 展現出來。 -
ViewModel
監聽模型資料的改變和控制檢視行為、處理使用者互動,簡單理解就是一個同步View 和 Model的物件,連線Model和View。
在MVVM架構下,View 和 Model 之間並沒有直接的聯絡,而是通過ViewModel進行互動,Model 和 ViewModel 之間的互動是雙向的, 因此View 資料的變化會同步到Model中,而Model 資料的變化也會立即反應到View 上。
ViewModel 通過雙向資料繫結把 View 層和 Model 層連線了起來,而View 和 Model 之間的同步工作完全是自動的,無需人為干涉,因此開發者只需關注業務邏輯,不需要手動操作DOM, 不需要關注資料狀態的同步問題,複雜的資料狀態維護完全由 MVVM 來統一管理。
注意, MVVM模型中, Model和View是不會直接連線的,而ViewModel則會以雙向連線的形式連線Model和View。
0. Vue的特性(優缺點)以及和其他框架的對比
Vue的優點
- 輕量級的框架
- 雙向資料繫結
- 指令
- 外掛化
與React的對比
節選自 Vue的官方文件,筆者我進行了一些梳理,想了解得具體些的話還是猛戳連結吧。
-
兩者具有許多的相似之處
- 使用 Virtual DOM
- 提供了響應式 (Reactive) 和元件化 (Composable) 的檢視元件。
- 將注意力集中保持在核心庫,而將其他功能如路由和全域性狀態管理交給相關的庫。
Vue與React的不同之處
-
- 元件的重渲染 React中元件的重渲染需要通過
shouldComponentUpdate
來避免不必要的子元件的重渲染,而Vue中元件的依賴是在渲染過程中自動追蹤的,所以系統能精確知曉哪個元件確實需要被重渲染。 - JSX vs Template
- 元件的重渲染 React中元件的重渲染需要通過
-
元件作用域的CSS 在React中,CSS 作用域是通過 CSS-in-JS 的方案實現的 (比如 styled-components、glamorous 和 emotion),而Vue則有更好的解決方案,如下:
``` <style scoped> @media (min-width: 250px) { .list-container:hover { background: orange; } } </style> ```這個可選
scoped
屬性會自動新增一個唯一的屬性 (比如data-v-21e5b78
) 為元件內 CSS 指定作用域,編譯的時候.list-container:hover
會被編譯成類似.list-container[data-v-21e5b78]:hover
,這樣就可以控制CSS只在這個元件內生效。- 更多的對比請移步Vue的官方文件吧,太多也不好記的
1. Vue的生命週期
具體可以參照官網的這張圖,左側以紅色框表示的都是階段
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdated
- updated
- beforeDestroy
- destroyed
大致過程就是
- 資料初始化(1~2)
完成資料觀測、屬性和方法的運算載入,event/wather時間回撥。 - dom掛載階段(3~4)
el被新建立的vm.$el替換並掛載到例項上去,之後呼叫鉤子函式。 - 資料更新階段(5~6)
資料更新,虛擬dom重渲染 - 元件解除安裝階段(7~8)
銷燬例項及子例項
2. Vue實現資料雙向繫結的原理
vue實現資料雙向繫結主要是採用資料劫持結合釋出者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在資料變動時釋出訊息給訂閱者,觸發相應監聽回撥。當把一個普通 Javascript 物件傳給 Vue 例項來作為它的 data 選項時,Vue 將遍歷它的屬性,用 Object.defineProperty 將它們轉為 getter/setter。使用者看不到 getter/setter,但是在內部它們讓 Vue 追蹤依賴,在屬性被訪問和修改時通知變化。
vue的資料雙向繫結 將MVVM作為資料繫結的入口,整合Observer,Compile和Watcher三者,通過Observer來監聽自己的model的資料變化,通過Compile來解析編譯模板指令,最終利用watcher搭起observer和Compile之間的通訊橋樑,達到資料變化 —>檢視更新;檢視互動變化(input)—>資料model變更雙向繫結效果。
3. Vue的路由實現
路由的實現有兩種:hash和history interface來實現前端路由,
hash在瀏覽器中符號“#”,#以及#後面的字元稱之為hash,用window.location.hash讀取;特點:
(1)hash雖然在URL中,但不被包括在HTTP請求中
(2)用來指導瀏覽器動作,對服務端安全無用,hash不會重載入頁面
history採用h5的新特性;且提供了兩個新方法:pushState(),replaceState()可以對瀏覽器歷史記錄棧進行修改,以及popState事件的監聽到狀態變更,不過history有個問題是:如果使用者直接在位址列中輸入並回車,瀏覽器重啟或重新載入時,history模式會將url修改的和正常請求後端一樣,此情況下,重新向後端傳送請求,後端如果沒有配置對應路由處理,則返回404,解決方法是後端配置一下。
4. Vue的路由傳參
<router-link :to="{path:'/index',params:{id:num}}">
<router-link :to="{ path:'/index' , query:{id:num}}">
然後通過$route.params來讀取資料,但路由傳遞引數值是物件的話就不行了會報錯,傳遞前用base64轉譯一下就可以了。
5. Vue元件間的引數傳遞
父元件與子元件傳值
父元件通過標籤上面定義傳值
<parent>
<child :child-msg="msg"></child> //這裡必須要用 - 代替駝峰
</parent>
data(){
return {
msg: [1,2,3]
};
}
子元件通過props
方法接受資料
子元件通過props來接收資料:
方式1:
props: ['childMsg']
方式2 :
props: {
childMsg: Array //這樣可以指定傳入的型別,如果型別不對,會警告
}
方式3:
props: {
childMsg: {
type: Array, //傳入的型別
default: [0,0,0] //這樣可以指定預設的值
}
}
子元件向父元件傳遞資料
子元件通過$emit
方法傳遞引數
<template>
<div @click="testClick"></div>
</template>
methods: {
testClick() {
this.$emit('test','123');
//$emit(even,value)even 是一個函式,value 是傳給父元件的值 , 觸發名為test方法, '123'為向父元件傳遞的資料
}
}
父元件通過v-on
(簡寫為@
)來監聽DOM事件,並在觸發時接收資料執行js函式。
<div>
<child @test="change" :msg="msg"></child> //監聽子元件觸發的test事件,然後呼叫change方法
</div>
methods: {
change(val) {
this.msg = val; // val: 123
}
}
非父子元件間的資料傳遞
如果2個元件不是父子元件那麼如何通訊呢?這時可以通過eventHub
來實現通訊.
所謂eventHub
就是建立一個事件中心,相當於中轉站,可以用它來傳遞事件和接收事件.
let Hub = new Vue(); //建立事件中心
元件1觸發:
<div @click="eve"></div>
methods: {
eve() {
Hub.$emit('change','hehe'); //Hub觸發事件
}
}
元件2接收:
<div></div>
created() {
Hub.$on('change', () => { //Hub接收事件
this.msg = 'hehe';
});
}
6. Vue響應資料變化的幾種做法
- methods: 每次獲取都會重新計算求值
- computed(計算屬性,有快取): 基於資料依賴進行快取,只有當資料變化時,才會重新求值。(計算屬性只有 getter,可以在需要的時候自己設定 setter)。computed 擅長處理的情景:一個數據受多個數據影響。
- watch: 當需要在資料變化時執行非同步操作或者消耗較大的操作時,比較有效。watch 擅長處理的情景:一個數據影響多個數據。
- v-model: 基於資料雙向繫結(對於 v-for 迴圈列表中的項,需要使用鍵值)
7. Vue的條件渲染
Vue的條件渲染涉及到兩個不同的關鍵字 v-if
和 v-show
v-if
v-if
是真正的條件渲染,它會適當地銷燬和重建DOM達到讓元素顯示和隱藏的效果。
(Vue 會盡可能高效地渲染元素,通常會複用已有元素而不是從頭開始渲染,可以看一下第二段程式)v-if
也是惰性的:如果在初始渲染時條件為假,則什麼也不做——直到條件第一次變為真時,才會開始渲染條件塊。
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
Vue 為你提供了一種方式來表達“這兩個元素是完全獨立的,不要複用它們”。
只需新增一個具有唯一值的 key
屬性即可,沒有 key
說明的話就會被複用:
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
注意,<label>
元素仍然會被高效地複用,因為它們沒有新增 key
屬性。
v-show
通過修改元素的display的CSS屬性讓其顯示或者隱藏,元素始終會被渲染並保留在DOM中。
<h1 v-show="ok">Hello!</h1>
//ok 在data裡進行賦值為true或者false
v-if
vs v-show
一般來說,v-if
有更高的切換開銷,而 v-show
有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show
較好;如果在執行時條件很少改變,則使用 v-if
較好。
歡迎諸位同道們留言補充ヾ(◍°∇°◍)ノ゙
參考連結
Vue官方教程
MVVM - 廖雪峰的官方網站
MVC,MVP 和 MVVM 的圖示 - 阮一峰的網路日誌
vue.js學習筆記(一):什麼是mvvm框架,vue.js的核心思想 - _林沖 - 部落格園
vue父子元件通訊 - Hi-Sen - 部落格園
Vue 成長之路(一) - 媛媛碼農成長記 - SegmentFault 思否
來源:https://segmentfault.com/a/1190000016268245