重整旗鼓,2019自結前端面試小冊【Vue.Js】

CHICAGO發表於2020-02-25

前言

臨近2019年的尾聲,是不是該為了更好的2020年再戰一回呢? ‘勝敗兵家事不期,包羞忍恥是男兒。江東子弟多才俊,捲土重來未可知’,那些在秋招失利的人,難道就心甘情願放棄嗎!

此文總結2019年以來本人經歷以及瀏覽文章中,較熱門的一些面試題,涵蓋從CSS到JS再到Vue再到網路等前端基礎到進階的一些知識。

總結面試題涉及的知識點是對自己的一個提升,也希望可以幫助到同學們,在2020年會有一個更好的競爭能力。

重整旗鼓,2019自結前端面試小冊【Vue.Js】

Module Four - Vue

「About Base」

講一講你對MVVM的理解?與MVC有什麼不同?

  • MVC指的是Model-View-Controller,即模型-檢視-控制器。
    • 使用MVC的目的就是將模型與檢視分離
    • MVC屬於單向通訊,必須通過Controller來承上啟下,既必須由控制器來獲取資料,將結果返回給前端,頁面重新渲染
  • MVVM指的是Model-View-ViewModel,即模型-檢視-檢視模型,「模型」指的是後端傳遞的資料,「檢視」指的是所看到的頁面,「檢視模型」是MVVM的核心,它是連線ViewModel的橋樑,實現view的變化會自動更新到viewModel中,viewModel中的變化也會自動顯示在view,是一種資料驅動檢視的模型

區別:

  • MVC中的ControlMVVM中演變成viewModel
  • MVVM通過資料來顯示檢視,而不是通過節點操作
  • MVVM主要解決了MVC中大量的DOM操作,使頁面渲染效能降低,載入速度慢,影響使用者體驗的問題

請說一下Vue響應式資料的原理?

Vue底層對於響應式資料的核心是object.definePropertyVue在初始化資料時,會給data中的屬性使用object.defineProperty重新定義屬性(劫持屬性的gettersetter),當頁面使用對應屬性時,會進行依賴收集(收集當前元件的watcher),如果屬性發生變化,會通知相關依賴進行更新操作

  • 總結: Vue通過資料劫持配合釋出者-訂閱者的設計模式,內部通過呼叫object.defineProperty()來劫持各個屬性的gettersetter,在資料變化的時候通知訂閱者,並觸發相應的回撥

Vue是如何實現資料雙向繫結的?

Vue資料雙向繫結是指:資料變化更新檢視,檢視變化更新資料,例如輸入框輸入內容變化時,data中的資料同步變化;data中的資料變化時,文字節點的內容同步變化

Vue主要通過以下4個步驟實現資料雙向繫結

  • 實現一個監聽器「Observer」:對資料物件進行遍歷,包括子屬性物件的屬性,利用Object.defineProperty()在屬性上都加上gettersetter,這樣後,給物件的某個值賦值,就會觸發setter,那麼就能監聽到資料變化
  • 實現一個解析器「Compile」:解析Vue模板指令,將模板中的變數都替換成資料,然後初始化渲染頁面檢視,並將每個指令對應的節點繫結更新函式,新增監聽資料的訂閱者,一旦資料有變動,收到通知,呼叫更新函式進行資料更新
  • 實現一個訂閱者「Watcher」:Watcher訂閱者是ObserverCompile之間通訊的橋樑,主要任務是訂閱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···
  • Vuedata中的陣列,進行了原型鏈的重寫,指向了自己所定義的陣列原型方法,當呼叫陣列的API時,可以通知依賴更新,如果陣列中包含著引用型別,會對陣列中的引用型別再次進行監控

Vue如何通過vm.$set()來解決物件新增/刪除屬性不能響應的問題?

由於JavaScript的限制,Vue無法檢測到物件屬性的新增或刪除。這是由於Vue會在初始化例項時對屬性的gettersetter進行劫持,所以屬性必須在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,在同級vnodeDiff過程中,可以根據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 → 例項銷燬之前呼叫,在這裡,例項仍然完全可以使用
  • destroyedVue例項銷燬後呼叫。呼叫該鉤子後,Vue例項指示的所有東西都會解綁,所有的事件監聽器會被移除,所有的子例項也會被銷燬(該鉤子在伺服器端渲染期間不被呼叫)

重整旗鼓,2019自結前端面試小冊【Vue.Js】


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-bindv-on的語法糖,用來在表單控制元件或元件上建立雙向繫結。

<input v-model='searchText'>

等價於

<input
    v-bind:value='searchText'
    v-on:input='searchText = $event.target.value'>
複製程式碼

在一個元件上使用v-model,預設會為元件繫結名為valueprop和名為input的事件


「譯」Vuex和單純的全域性物件有什麼區別?

vuex和全域性物件主要有兩大區別:

  • vuex的狀態儲存是響應式的。當vue元件從store中讀取狀態時,若store中的狀態發生變化,那麼相應的元件也會得到高效更新
  • 不呢能直接改變store中的狀態,改變store中的狀態唯一方法是顯示地提交mutationcommit)。這樣使得我們可以方便地跟蹤每一個狀態的變化

「譯」為什麼vuex的mutation中不能做非同步操作?

vuex中所有的狀態更新的唯一方式都是提交mutation,非同步操作需要通過action來提交mutationdispatch)。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地使用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:computedwatch區別在於用法上的不同,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鉤子
  • 提供includeexclude屬性,兩者都支援字串或正規表示式
    • 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頁面初始化時載入相應的HtmlJavaScriptCss,一旦頁面載入完成,SPA不會因為使用者的操作而進行頁面的重新載入或跳轉,取而代之的是利用路由機制實現Html內容的變換,UI與使用者的互動,避免頁面的重新載入

  • 優點:
    • 使用者體驗好,載入速度快,內容改變不需要重新載入整個頁面,避免了不必要的跳轉和重複渲染
    • SPA相對對伺服器壓力小
    • 前後端職責分離,架構更清晰,前端進行互動邏輯,後端負責資料處理
  • 缺點:
    • 首次載入耗時較多(為實現單頁面Web應用功能及顯示效果,需要在載入頁面的時候將JavaScriptCss統一載入,部分頁面按需載入)
    • 由於單頁面應用在一個頁面中顯示所有的內容,所以不能使用瀏覽器的前進後退功能,所有的頁面切換需要自己建立堆疊管理
    • 不利於SEO優化

如何讓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(pushStatereplaceState),這兩個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」

重整旗鼓,2019自結前端面試小冊【Vue.Js】

vuex有什麼優缺點?

  • 優點
    • 解決了非父子元件的訊息傳遞(將資料存放在state中)
    • 減少了Ajax請求次數,有些情景可以直接從記憶體中的State獲取
  • 缺點
    • 重新整理瀏覽器,vuex中的State就會重新變回初始化狀態

vuex有哪幾種屬性?

  • Statevuex的基本資料,用來儲存變數
  • Getter :從基本資料state派生的資料,相當於state的計算屬性
  • Mutation :提交更新資料的方法,必須是同步的(需要非同步則使用action)。每個mutation都有一個字串的事件型別(type)和一個回撥函式(handler
  • Action :和mutation的功能大致相同,不同在於
    • action提交的是mutation,而不是直接變更狀態
    • action可以包含任意非同步操作
  • Module :模組化vuex,可以讓每一個模組擁有自己的statemutationactiongetter,使得結構清晰,方便管理

vuex 中的 state 有什麼特性?

  • vuex就是一個倉庫,倉庫裡面放了很多物件,其中state就是資料來源存放地
  • state裡面存放的資料是響應式的,Vue元件從store中讀取資料,若是store中的資料改變,依賴這個資料的元件也會更新資料
  • 它通過mapState把全域性的stategetters對映到當前元件的computed計算屬性中

vuex 中的 getters 有什麼特性?

  • getters可以對state進行計算操作,可以把它看做storecomputed計算屬性
  • 雖然在元件中也可以做計算屬性,但getters可以在多個元件之間複用
  • 如果一個狀態只在一個元件內使用,是可以不用getters

Vue 中對 Ajax 請求程式碼應該寫在元件的 methods 中還是 vuex 的 actions 中?

  • 如果請求的資料是不被其他元件公用的,僅僅在請求的元件內使用,就不需要放入vuexstate
  • 如果被其他地方複用,可以將請求放入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資源

相關文章