前言
臨近2019年的尾聲,是不是該為了更好的2020年再戰一回呢? ‘勝敗兵家事不期,包羞忍恥是男兒。江東子弟多才俊,捲土重來未可知’,那些在秋招失利的人,難道就心甘情願放棄嗎!
此文總結2019年以來本人經歷以及瀏覽文章中,較熱門的一些面試題,涵蓋從CSS到JS再到Vue再到網路等前端基礎到進階的一些知識。
總結面試題涉及的知識點是對自己的一個提升,也希望可以幫助到同學們,在2020年會有一個更好的競爭能力。
css篇
- juejin.im/post/5e040e…Javavscript篇
- juejin.im/post/5e2122…ECMAScript 6篇
- juejin.im/post/5e2962…
Module Four - Vue
「About Base」
講一講你對MVVM的理解?與MVC有什麼不同?
MVC
指的是Model-View-Controller
,即模型-檢視-控制器。- 使用
MVC
的目的就是將模型與檢視分離 MVC
屬於單向通訊,必須通過Controller
來承上啟下,既必須由控制器來獲取資料,將結果返回給前端,頁面重新渲染
- 使用
MVVM
指的是Model-View-ViewModel
,即模型-檢視-檢視模型,「模型」指的是後端傳遞的資料,「檢視」指的是所看到的頁面,「檢視模型」是MVVM
的核心,它是連線View
與Model
的橋樑,實現view
的變化會自動更新到viewModel
中,viewModel
中的變化也會自動顯示在view
上,是一種資料驅動檢視的模型
區別:
MVC
中的Control
在MVVM
中演變成viewModel
MVVM
通過資料來顯示檢視,而不是通過節點操作MVVM
主要解決了MVC
中大量的DOM
操作,使頁面渲染效能降低,載入速度慢,影響使用者體驗的問題
請說一下Vue響應式資料的原理?
Vue
底層對於響應式資料的核心是object.defineProperty
,Vue
在初始化資料時,會給data
中的屬性使用object.defineProperty
重新定義屬性(劫持屬性的getter
和setter
),當頁面使用對應屬性時,會進行依賴收集(收集當前元件的watcher
),如果屬性發生變化,會通知相關依賴進行更新操作
- 總結:
Vue
通過資料劫持配合釋出者-訂閱者的設計模式,內部通過呼叫object.defineProperty()
來劫持各個屬性的getter
和setter
,在資料變化的時候通知訂閱者,並觸發相應的回撥
Vue是如何實現資料雙向繫結的?
Vue資料雙向繫結是指:資料變化更新檢視,檢視變化更新資料,例如輸入框輸入內容變化時,data中的資料同步變化;data中的資料變化時,文字節點的內容同步變化
Vue主要通過以下4個步驟實現資料雙向繫結
- 實現一個監聽器「Observer」:對資料物件進行遍歷,包括子屬性物件的屬性,利用
Object.defineProperty()
在屬性上都加上getter
和setter
,這樣後,給物件的某個值賦值,就會觸發setter
,那麼就能監聽到資料變化 - 實現一個解析器「Compile」:解析
Vue
模板指令,將模板中的變數都替換成資料,然後初始化渲染頁面檢視,並將每個指令對應的節點繫結更新函式,新增監聽資料的訂閱者,一旦資料有變動,收到通知,呼叫更新函式進行資料更新 - 實現一個訂閱者「Watcher」:
Watcher
訂閱者是Observer
和Compile
之間通訊的橋樑,主要任務是訂閱Observer
中的屬性值變化的訊息,當收到屬性值變化的訊息時,觸發解析器Compile
中對應的更新函式 - 實現一個訂閱器「Dep」:訂閱器採用釋出-訂閱設計模式,用來收集訂閱者
Watcher
,對監聽器Observer
和訂閱者Watcher
進行統一管理
Vue如何實現物件和陣列的監聽?
由於
Object.defineProperty()
只能對屬性進行資料劫持,而不能對整個物件(陣列)進行資料劫持,因此Vue框架通過遍歷陣列和物件,對每一個屬性進行劫持,從而達到利用Object.defineProperty()
也能對物件和陣列(部分方法的操作)進行監聽
直接給一個陣列項賦值,Vue能檢測到變化嗎?
由於JavaScript
的限制,Vue
不能檢測到以下陣列的變動
- 當利用索引直接設定一個陣列項時,例如
vm.items[indexOfItem] = newValue
- 當修改陣列的長度時,例如
vm.items.length = newLength
為了解決第一個問題,Vue
提供了以下操作方式
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// vm.$set,Vue.set的一個別名
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
複製程式碼
為了解決第二個問題,Vue
提供了以下操作方式
// Array.prototype.splice
vm.items.splice(newLength - 1)
複製程式碼
講一講Vue是如何檢測陣列的變化?
- 核心思想:使用了函式劫持的方式,重寫了陣列的方法(
push,pop,unshift,shift···
) Vue
將data
中的陣列,進行了原型鏈的重寫,指向了自己所定義的陣列原型方法,當呼叫陣列的API
時,可以通知依賴更新,如果陣列中包含著引用型別,會對陣列中的引用型別再次進行監控
Vue如何通過vm.$set()
來解決物件新增/刪除屬性不能響應的問題?
由於
JavaScript
的限制,Vue無法檢測到物件屬性的新增或刪除。這是由於Vue會在初始化例項時對屬性的getter
和setter
進行劫持,所以屬性必須在data物件上存在才能讓Vue將它們轉換為響應式資料。
Vue
提供了Vue.set(object, propertyName, value) / vm.$set(object, propertyName, value)
來實現為物件新增響應式屬性,其原理如下:
- 如果目標是陣列,直接使用陣列的
splice
方法觸發響應式 - 如果目標是物件,會先判斷物件屬性是否存在,物件是否是響應式,最終如果要對屬性進行響應式處理,則是通過呼叫
defineReactive()
方法進行響應式處理(defineReactive()
是Vue對Object.defineProperty()
的二次封裝)
為什麼Vue要採取非同步渲染?
因為如果不採用非同步渲染,那麼每次更新資料都會進行重新渲染,為了提高效能,Vue
通過非同步渲染的方式,在本輪資料更新後,再去非同步更新檢視
「譯」Object.defineProperty有什麼缺點?(為什麼Vue3.0開始使用Proxy實現響應式)
Object.defineProperty
只能劫持物件的屬性,因此需要遍歷物件的每個屬性,而Proxy
可以直接代理物件Object.defineProperty
對新增屬性需要手動進行觀察,由於Object.defineProperty
劫持的是物件的屬性(第一點),所以新增屬性時,需要重新遍歷物件,對其新增屬性再使用Object.defineProperty
進行劫持 (正是這個原因導致我們在給data
中的陣列或物件新增屬性時,需要使用$set
才能保證檢視可以更新)Proxy
效能高,支援13種攔截方式
虛擬Dom的優缺點?
優點:
- 保證效能下限:框架的虛擬
Dom
需要適配任何上層API可能產生的操作,它的一些Dom
操作的實現必須是普遍適用的,所以它的效能並不是最優的,但比起粗暴的Dom
操作要好很躲,因此保證了效能的下限 - 無需手動操作
Dom
:框架會根據虛擬Dom
和資料的雙向繫結,幫我們更新檢視,提高開發效率 - 跨平臺:虛擬
Dom
本質上是JavaScript
物件,而真實Dom
與平臺相關,相比下虛擬Dom
可以更好地跨平臺操作
缺點:
- 無法進行極致優化
虛擬Dom的實現原理?
虛擬Dom
的實現原理主要包括以下三部分:
- 用
JavaScript
物件模擬真實Dom
樹,對真實Dom
進行抽象 - 通過
diff
演算法對兩顆虛擬Dom
物件進行比較 - 通過
patch
演算法將兩個虛擬Dom
物件的差異應用到真實Dom
樹上
nextTick實現原理是什麼? 在Vue中有什麼作用
- 原理:
EventLoop
事件迴圈 - 作用:在下次
dom
更新迴圈結束後執行延遲迴調,當我們修改資料之後立即使用nextTick()
來獲取最新更新的Dom
watch中的deep:true是如何實現的?
當使用者指定了watch
中的deep:true
時,如果當前監控的值是陣列型別(物件型別),會對物件中的每一項進行求值,此時會將當前watcher
存入到對應屬性的依賴中,這樣陣列中的物件發生變化也會通知資料進行更新
缺點:由於需要對每一項都進行操作,效能會降低,不建議多次使用deep:true
為什麼v-if與v-for不建議連在一起使用?
v-for
優先順序高於v-if
,如果連在一起使用的話會把v-if
給每一個元素都新增上,重複執行於每一個v-for
迴圈中,會造成效能浪費
「譯」元件的data為什麼要寫成函式形式
在Vue
中,元件都是可複用的,一個元件建立好後,可以在多個地方重複使用,而不管複用多少次,元件內的data
都必須是相互隔離,互不影響的,如果data
以物件的形式存在,由於Javascript
中物件是引用型別,作用域沒有隔離,因此data
必須以函式的形式返回
- 總結:為了實現每個元件例項可以維護獨立的資料拷貝,不會相互影響
❗ 小知識: new Vue
根元件不需要複用,因此不需要以函式方式返回
「譯」v-for中的key的作用是什麼?
key
是為每個vnode
指定唯一的id
,在同級vnode
的Diff
過程中,可以根據key
快速的進行對比,來判斷是否為相同節點,並利用key
的唯一性生成map
來更快的獲取相應的節點,另外指定key
後,可以保證渲染的準確性
Vue每個生命週期什麼時候被呼叫?
beforeCreate
→ 在例項初始化之後,資料觀測(data observer
)之前被呼叫created
→ 例項已經建立完成之後被呼叫。在這裡,例項已完成以下配置:- 資料觀測(
data observer
) - 屬性和方法的運算
watch/event
事件回撥- 但這裡還沒有
$el
- 資料觀測(
beforeMount
→ 在掛載開始之前被呼叫,相關的render
函式首次被呼叫mounted
→$el
被新建立的vm.$el
替換,並掛載到例項上之後呼叫該鉤子beforeUpdate
→ 資料更新時呼叫,發生在虛擬DOM
重新渲染和打補丁之前updated
→ 由於資料更改導致的虛擬DOM
重新渲染和打補丁,在這之後會呼叫該鉤子(該鉤子在伺服器端渲染期間不被呼叫)beforeDestroy
→ 例項銷燬之前呼叫,在這裡,例項仍然完全可以使用destroyed
→Vue
例項銷燬後呼叫。呼叫該鉤子後,Vue
例項指示的所有東西都會解綁,所有的事件監聽器會被移除,所有的子例項也會被銷燬(該鉤子在伺服器端渲染期間不被呼叫)
Vue每個生命週期內部可以做什麼事?
created
→ 例項已經建立完成,由於它是最早觸發的,所以可以進行一些資料,資源的請求mounted
→ 例項已經掛載完成,可以進行一些DOM
操作beforeUpdate
→ 可以在該鉤子中進一步地更改狀態,這不會觸發附加的渲染過程updated
→ 可以執行依賴於DOM
的操作。但在大多數情況下,應避免在該鉤子中更改狀態,因為這可能導致更新無限迴圈destroyed
→ 可以執行一些優化操作,例如清空定時器,清理快取,解除事件繫結等
Vue元件有哪些宣告生命週期鉤子?
「beforeCreate
」、「created
」、「beforeMount
」、「mounted
」、「beforeUpdate
」、「updated
」、「beforeDestroy
」、「destroyed
」
❗ 小知識:
<keep-alive>
擁有自己獨立的鉤子函式 activated
| deactivated
activated
→ 在被<keep-alive>
包裹的元件中才有效,當元件被啟用時使用該鉤子deactivated
→ 在被<keep-alive>
包裹的元件中才有效,當元件被停止時使用該鉤子
「譯」Vue的父元件和子元件生命週期鉤子執行順序是什麼?
- 理解渲染過程:
父元件掛載完成必須是等到子元件都掛載完成之後,才算父元件掛載完,所以父元件的
mounted
肯定是在子元件mounted
之後
So:「父」beforeCreate → 「父」created → 「父」beforeMount → 「子」beforeCreate → 「子」created → 「子」beforeMount → 「子」mounted → 「父」mounted
-
子元件更新過程(取決於對父元件是否有影響)
- 影響到父元件: 「父」beforeUpdate → 「子」beforeUpdate → 「子」updated → 「父」updated
- 不影響父元件: 「子」beforeUpdate → 「子」updated
-
父元件更新過程(取決於對子元件是否有影響)
- 影響到子元件: 「父」beforeUpdate → 「子」beforeUpdate → 「子」updated → 「父」updated
- 不影響子元件: 「父」beforeUpdate → 「父」updated
-
銷燬過程
- 「父」beforeDestroy → 「子」beforeDestroy → 「子」destroyed → 「父」destroyed
父元件可以監聽到子元件的生命週期嗎?
比如有一個父元件Parent和子元件Child,如果父元件監聽到子元件掛載
mounted
就做一些邏輯處理、
- 方式一
// Parent.vue
<Child @mounted='doSomething' />
// Child.vue
mounted(){
this.$emit('mounted')
}
複製程式碼
- 方式二(更簡單 - 通過@hook來監聽)
// Parent.vue
<Child @hook:mounted='doSomething' />
# @hook可以監聽其他生命週期
複製程式碼
怎麼理解vue的單向資料流
- 在
vue
中,父元件可以通過prop
將資料傳遞給子元件,但這個prop
只能由父元件來修改,子元件修改的話會丟擲錯誤 - 如果是子元件想要修改資料,只能通過
$emit
由子元件派發事件,並由父元件接收事件進行修改
為什麼子元件不可以修改父元件傳遞的Prop?(為什麼vue提倡單向資料流)
由於vue
提倡單向資料流,即父級props
的更新會流向子元件,但反過來則不行。這是為了防止意外的改變父元件的狀態,使得應用的資料流變得難以理解。如果破壞了單項資料流,當應用複雜時,debug的成本將會非常高
元件間有哪些通訊方式?
-
父子元件通訊
props
/event
$parent
/$children
ref
provide
/inject
.sync
-
非父子元件通訊
eventBus
- 通過根例項
$root
vuex
$attr
/$listeners
provide
/inject
❗ 小知識: 關於.sync
的使用
假設有一個元件 comp
<comp :foo.sync="bar"></comp>
傳遞foo值並用sync修飾,會被擴充套件成
<comp :foo="bar" @update:foo="val => bar = val"></comp>
複製程式碼
當子元件comp需要更新foo的值時,它需要顯示地觸發一個更新事件
this.$emit('update:foo', newValue)
複製程式碼
說一說vue的動態元件
多個元件通過同一個掛載點進行元件的切換,
is
的值是哪個元件的名稱,那麼頁面就會顯示哪個元件
<div :is='xxx'></div>
複製程式碼
講一講遞迴元件的用法
元件是可以在它們自己的模板中呼叫自身的,不過它們只能通過
name
選項來做這件事
首先我們要知道,既然是遞迴元件,那麼一定要有一個結束的條件,否則就會導致元件無限迴圈使用,最終出現
max stack size exceeded
的錯誤,也就是棧溢位。所以,我們應該使用v-if = 'false'
來作為遞迴元件的結束條件,當遇到v-if = 'false'
時,元件將不會再進行渲染
自定義元件的語法糖v-model是怎麼樣實現的?(v-model如何實現雙向繫結)
v-model
本質是v-bind
和v-on
的語法糖,用來在表單控制元件或元件上建立雙向繫結。
<input v-model='searchText'>
等價於
<input
v-bind:value='searchText'
v-on:input='searchText = $event.target.value'>
複製程式碼
在一個元件上使用v-model
,預設會為元件繫結名為value
的prop
和名為input
的事件
「譯」Vuex和單純的全域性物件有什麼區別?
vuex
和全域性物件主要有兩大區別:
vuex
的狀態儲存是響應式的。當vue
元件從store
中讀取狀態時,若store
中的狀態發生變化,那麼相應的元件也會得到高效更新- 不呢能直接改變
store
中的狀態,改變store
中的狀態唯一方法是顯示地提交mutation
(commit
)。這樣使得我們可以方便地跟蹤每一個狀態的變化
「譯」為什麼vuex的mutation中不能做非同步操作?
vuex
中所有的狀態更新的唯一方式都是提交mutation
,非同步操作需要通過action
來提交mutation
(dispatch
)。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地使用vuex
每個mutation
執行完後都會對應得到一個新的狀態變更,這樣devtools
就可以打個快照存下來,然後就可以實現time-travel
了。
如果mutation
支援非同步操作,就沒有辦法知道狀態是何時更新,無法很好的進行狀態追蹤,影響除錯效率
v-show / v-if 的區別是什麼?
v-if
指如果條件不成立則不會渲染當前指令所在節點的Dom
元素,會在切換過程中對條件塊的事件監聽器和子元件進行銷燬和重建v-show
只是基於css
進行切換,不管條件是什麼,都會進行渲染(切換display:block | none
)
So:v-if
切換的開銷較大,而v-show
初始化的開銷較大,所以在需要頻繁切換顯示和隱藏的Dom
元素時,使用v-show
更合適,渲染後很少進行切換則使用v-if
較合適
computed / watch 的區別是什麼?
computed
是依賴於其他屬性的一個計算值,並且具備快取,只有當依賴的值發生變化才會更新(自動監聽依賴值的變化,從而動態返回內容)watch
是在監聽的屬性發生變化的時候,觸發一個回撥,在回撥中執行一些邏輯
So:computed
和watch
區別在於用法上的不同,computed
適合在模板渲染中,如果是需要通過依賴來獲取動態值,就可以使用計算屬性。而如果是想在監聽值變化時執行業務邏輯,就使用watch
computed / methods 的區別是什麼?
computed
是基於它們響應式依賴進行快取,只有在依賴值發生變化,才會進行計算求值methods
每次使用都會執行相應的方法
Vue中 v-html 有什麼作用?會導致什麼問題?
v-html
可以用來識別HTML標籤並渲染出去
導致問題: 在網站上動態渲染任意Html
,很容易導致受到Xss
攻擊,所以只能在可信內容上使用v-html
,且永遠不能用於使用者提交的內容上
keep-alive在vue中的作用是什麼?
包裹在<keep-alive>
裡元件,在切換時會儲存其元件的狀態,使其不被銷燬,防止多次渲染
- 一般結合路由和動態元件一起使用,用於快取元件
keep-alive
擁有兩個獨立的生命週期(activated
|deactivated
),使keep-alive
包裹的元件在切換時不被銷燬,而是快取到記憶體中並執行deactivated
鉤子,切換回元件時會獲取記憶體,渲染後執行activated
鉤子- 提供
include
和exclude
屬性,兩者都支援字串或正規表示式include
表示只有名稱匹配的元件才會被快取exclude
表示任何名稱匹配的元件都不會被快取exclude
優先順序高於include
如何新增自定義指令?
- 建立區域性指令
var app = new Vue({
el: '#app',
data: {
},
// 建立指令(可以多個)
directives: {
// 指令名稱
dir1: {
inserted(el) {
// toDo
}
}
}
})
複製程式碼
- 建立全域性指令
Vue.directive('dir2', {
inserted(el) {
// inserted 表示元素插入時
// toDo
}
})
複製程式碼
- 指令使用
<div id="app">
<div :dir1='..'></div>
</div>
複製程式碼
如何自定義過濾器
- 建立區域性過濾器
var app = new Vue({
el: '#app',
data: {
},
// 建立指令(可以多個)
filters: {
// 指令名稱
newfilter:function(value){
// toDo
}
}
})
複製程式碼
- 建立全域性過濾器
Vue.filter('newfilter', function (value) {
// toDo
})
複製程式碼
- 過濾器使用
<div>{{xxx | newfilter}}</div>
複製程式碼
vue常用修飾符有哪些,有什麼用?
.prevent
:攔截預設事件.passive
:不攔截預設事件.stop
:阻止事件冒泡.self
:當事件發生在該元素而不是子元素的時候會觸發.capture
:事件偵聽,事件發生的時候會呼叫
Class / Style 如何動態繫結
Class可以通過物件語法和陣列語法進行動態繫結
- 物件語法
<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
data: {
isActive: true,
hasError: false
}
複製程式碼
- 陣列語法
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
複製程式碼
Style也可以通過物件語法和陣列語法進行動態繫結
- 物件語法
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
複製程式碼
- 陣列語法
<div v-bind:style="[styleColor, styleSize]"></div>
data: {
styleColor: {
color: 'red'
},
styleSize:{
fontSize:'23px'
}
}
複製程式碼
說說對SPA單頁面的理解,以及它的優缺點是什麼?
SPA(singlg-page application)
僅在Web頁面初始化時載入相應的Html
,JavaScript
,Css
,一旦頁面載入完成,SPA
不會因為使用者的操作而進行頁面的重新載入或跳轉,取而代之的是利用路由機制實現Html
內容的變換,UI
與使用者的互動,避免頁面的重新載入
- 優點:
- 使用者體驗好,載入速度快,內容改變不需要重新載入整個頁面,避免了不必要的跳轉和重複渲染
- SPA相對對伺服器壓力小
- 前後端職責分離,架構更清晰,前端進行互動邏輯,後端負責資料處理
- 缺點:
- 首次載入耗時較多(為實現單頁面Web應用功能及顯示效果,需要在載入頁面的時候將
JavaScript
,Css
統一載入,部分頁面按需載入) - 由於單頁面應用在一個頁面中顯示所有的內容,所以不能使用瀏覽器的前進後退功能,所有的頁面切換需要自己建立堆疊管理
- 不利於SEO優化
- 首次載入耗時較多(為實現單頁面Web應用功能及顯示效果,需要在載入頁面的時候將
如何讓css僅在當前元件中起作用
在
<style>
標籤上寫入scoped
即可
「About Router」
關於路由,route / router 有什麼區別?
route
表示路由資訊物件,包括path
,params
,hash
,query
,fullPath
,matched
,name
等路由資訊引數router
表示路由例項物件,包括了路由的跳轉方法,鉤子函式等
「譯」 vue-Router中有哪些導航守衛
- 「全域性前置鉤子」:
beforeEach
,beforeResolve
,afterEach
- 「路由獨享守衛」:
beforeEnter
- 「元件內部守衛」:
beforeRouteEnter
,beforeRouteUpdate
,beforeRouteLeave
導航解析流程:
- 導航被觸發
- 在失活的元件裡呼叫
beforeRouteLeave
離開守衛 - 呼叫全域性的
beforeEach
守衛 - 在重用的元件裡呼叫
beforeRouteUpdate
守衛 - 在路由配置裡呼叫
beforeEnter
守衛 - 解析非同步路由元件
- 在被啟用的元件裡呼叫
beforeRouteEnter
守衛 - 呼叫全域性的
beforeResolve
守衛 - 導航被確認
- 呼叫全域性的
afterEach
守衛 - 觸發
Dom
更新 - 用建立好的例項呼叫
beforeRouteEnter
守衛中傳給next
的回撥
「譯」vue-Router 中 hash / history 兩種模式有什麼區別?
hash
模式會在url
上顯示'#',而history
模式沒有- 重新整理頁面時,
hash
模式可以正常載入到hash
值對應的頁面,history
模式沒有處理的話,會返回404,一般需要後端將所有頁面都配置重定向到首頁路由 - 相容性上,
hash
模式可以支援低版本瀏覽器和IE
「譯」 vue-router 中 hash / history 是如何實現的?
hash
模式#
後面hash
值的變化,不會導致瀏覽器向伺服器發出請求,瀏覽器不發出請求,就不會重新整理頁面,同時通過監聽hashchange
事件可以知道hash
發生了哪些變化。根據hash
變化來實現頁面的區域性更新
history
模式history
模式的實現,主要是Html5
標準釋出的兩個Api(pushState
和replaceState
),這兩個Api可以改變url
,但是不會傳送請求,這樣就可以監聽url
的變化來實現區域性更新
怎麼定義 vue-router 的動態路由?怎麼獲取傳過來的值
- 動態路由的建立,主要是使用
path
屬性過程中,使用動態路徑引數,以冒號開頭
{
path:'/details/:id',
name:'Details',
components:Details
}
# 訪問`details`字首下的路徑,例如`details/1`,`details/2`等,都會對映到`Details`這個元件
複製程式碼
- 當匹配到
/details
下的路由時,引數值會被設定到this.$route.params
下,所以通過這個屬性可以獲取動態引數
this.$route.params.id
複製程式碼
vue-router 傳參方式有哪些?
- 通過
params
- 只能用
name
,不能用path
- 引數不會顯示在
url
上 - 瀏覽器強制重新整理會清空引數
- 只能用
- 通過
query
- 只能用
path
,不能用name
name
可以使用path
路徑- 引數會顯示在
url
上 - 瀏覽器重新整理不清空引數
- 只能用
「About Vuex」
vuex有什麼優缺點?
- 優點
- 解決了非父子元件的訊息傳遞(將資料存放在
state
中) - 減少了
Ajax
請求次數,有些情景可以直接從記憶體中的State
獲取
- 解決了非父子元件的訊息傳遞(將資料存放在
- 缺點
- 重新整理瀏覽器,
vuex
中的State
就會重新變回初始化狀態
- 重新整理瀏覽器,
vuex有哪幾種屬性?
State
:vuex
的基本資料,用來儲存變數Getter
:從基本資料state
派生的資料,相當於state
的計算屬性Mutation
:提交更新資料的方法,必須是同步的(需要非同步則使用action
)。每個mutation
都有一個字串的事件型別(type
)和一個回撥函式(handler
)Action
:和mutation
的功能大致相同,不同在於action
提交的是mutation
,而不是直接變更狀態action
可以包含任意非同步操作
Module
:模組化vuex
,可以讓每一個模組擁有自己的state
,mutation
,action
,getter
,使得結構清晰,方便管理
vuex 中的 state 有什麼特性?
vuex
就是一個倉庫,倉庫裡面放了很多物件,其中state
就是資料來源存放地state
裡面存放的資料是響應式的,Vue
元件從store
中讀取資料,若是store
中的資料改變,依賴這個資料的元件也會更新資料- 它通過
mapState
把全域性的state
和getters
對映到當前元件的computed
計算屬性中
vuex 中的 getters 有什麼特性?
getters
可以對state
進行計算操作,可以把它看做store
的computed
計算屬性- 雖然在元件中也可以做計算屬性,但
getters
可以在多個元件之間複用 - 如果一個狀態只在一個元件內使用,是可以不用
getters
Vue 中對 Ajax 請求程式碼應該寫在元件的 methods 中還是 vuex 的 actions 中?
- 如果請求的資料是不被其他元件公用的,僅僅在請求的元件內使用,就不需要放入
vuex
的state
裡 - 如果被其他地方複用,可以將請求放入
action
裡,方便複用;如果不需要複用這個請求,直接寫在Vue
檔案裡會更方便
「About SSR」
使用過 SSR 嗎?說一說對 SSR 的理解
Vue.js
是構建客戶端應用程式的框架,預設情況下,可以在瀏覽器中輸出Vue
元件,進行生成Dom
和操作Dom
。然而,也可以將同一個元件渲染為伺服器的Html
字串,將它們直接傳送給瀏覽器,最後將這些靜態標記啟用為客戶端上完全可以互動的應用程式
即:
SSR
大致意思就是vue
在客戶端將標籤渲染成整個html
片段的工作交給服務端完成,服務端形成的Html
片段直接返回給前端,這個過程就叫做SSR
(服務端渲染)
服務端渲染SSR的優點:
- 更好的SEO:由於
SPA
頁面的內容是通過Ajax
獲取,而搜尋引擎爬取工具並不會等待Ajax
非同步完成後再抓取頁面內容,所以在SPA
中是抓取不到頁面通過Ajax
獲取到的內容;而SSR
是直接由伺服器返回已經渲染好的頁面(資料已經包含在頁面中),所以搜尋引擎爬取工具可以抓取渲染好的頁面 - 更快的內容到達事件(首屏載入更快):
SPA
會等待所有Vue
編譯後的Js
檔案都下載完成後,才開始進行頁面渲染,檔案下載等需要一定時間,所以首屏渲染需要一定時間;而SSR
直接由伺服器渲染好頁面直接返回顯示,無需等待下載Js
檔案後再去渲染,所以SSR
有更快的內容到達時間
服務端渲染SSR的缺點:
- 更多的開發條件限制:例如服務端渲染只支援
beforeCreate
,created
生命週期鉤子,這會導致一些外部擴充套件庫需要特殊處理,才能在服務端渲染應用程式中執行;並且與可以部署在任何靜態檔案伺服器上的完全靜態單頁面應用程式SPA
不同,伺服器渲染應用程式需要處於NodeJs
環境下執行 - 更多的伺服器負載:在
NodeJs
中渲染完整的應用程式,顯然會比僅僅提供靜態檔案的server
更佔用CPU資源