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

前言

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

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

總結面試題涉及的知識點是對本身的一個提高,也但願能夠幫助到同窗們,在2020年會有一個更好的競爭能力。前端

Module Four - Vue

「About Base」

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

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

區別:vue

  • MVC中的ControlMVVM中演變成viewModel
  • MVVM經過數據來顯示視圖,而不是經過節點操做
  • MVVM主要解決了MVC中大量的DOM操做,使頁面渲染性能下降,加載速度慢,影響用戶體驗的問題

請說一下Vue響應式數據的原理?

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

  • 總結: Vue經過數據劫持配合發佈者-訂閱者的設計模式,內部經過調用object.defineProperty()來劫持各個屬性的gettersetter,在數據變化的時候通知訂閱者,並觸發相應的回調

講一講Vue是如何檢測數組的變化?

  • 核心思想:使用了函數劫持的方式,重寫了數組的方法(push,pop,unshift,shift···
  • Vuedata中的數組,進行了原型鏈的重寫,指向了本身所定義的數組原型方法,當調用數組的API時,能夠通知依賴更新,若是數組中包含着引用類型,會對數組中的引用類型再次進行監控

爲何Vue要採起異步渲染?

由於若是不採用異步渲染,那麼每次更新數據都會進行從新渲染,爲了提升性能,Vue經過異步渲染的方式,在本輪數據更新後,再去異步更新視圖面試


「譯」Object.defineProperty有什麼缺點?(爲何Vue3.0開始使用Proxy實現響應式)

  • Object.defineProperty只能劫持對象的屬性,所以須要遍歷對象的每一個屬性,而Proxy能夠直接代理對象
  • Object.defineProperty對新增屬性須要手動進行觀察,因爲Object.defineProperty劫持的是對象的屬性(第一點),因此新增屬性時,須要從新遍歷對象,對其新增屬性再使用Object.defineProperty進行劫持 (正是這個緣由致使咱們在給data中的數組或對象新增屬性時,須要使用$set才能保證視圖能夠更新)
  • Proxy性能高,支持13種攔截方式

nextTick實現原理是什麼? 在Vue中有什麼做用

  • 原理:EventLoop事件循環
  • 做用:在下次dom更新循環結束後執行延遲迴調,當咱們修改數據以後當即使用nextTick()來獲取最新更新的Dom

watch中的deep:true是如何實現的?

當用戶指定了watch中的deep:true時,若是當前監控的值是數組類型(對象類型),會對對象中的每一項進行求值,此時會將當前watcher存入到對應屬性的依賴中,這樣數組中的對象發生變化也會通知數據進行更新vue-router

缺點:因爲須要對每一項都進行操做,性能會下降,不建議屢次使用deep:truevuex


爲何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實例指示的全部東西都會解綁,全部的事件監聽器會被移除,全部的子實例也會被銷燬(該鉤子在服務器端渲染期間不被調用)


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

怎麼理解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鉤子


如何新增自定義指令?

  • 建立局部指令
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 :事件偵聽,事件發生的時候會調用

vue等單頁面應用優缺點是什麼?

  • 優勢:vue的目的是經過儘量簡單的API實現相應的數據綁定和組合的視圖組件,核心是一個響應的數據綁定系統。MVVM,數據驅動,組件化,輕量,簡潔,高效,快速。
  • 缺點
    • 不支持低版本的瀏覽器,最低只支持IE9
    • 不利於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」

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文件裏會更方便
相關文章
相關標籤/搜索