1. 程式人生 > 實用技巧 >Vue 面試題總結

Vue 面試題總結

1. Vue 框架的優點是什麼?

(1)輕量級框架:只關注檢視層,大小隻有幾十Kb;

(2)簡單易學:文件通順清晰,語法簡單;

(3)資料雙向繫結,資料檢視結構分離,僅需操作資料即可完成頁面相應的更新;

(4)元件化開發:工程結構清晰,程式碼維護方便;

(5)虛擬 DOM載入 HTML 節點,執行效率高。


2. 什麼是 MVVM?

MVVM 是Model-View-ModelView的縮寫,是一種脫胎於 MVC 模式的設計模式

Model 代表資料層,負責存放業務相關的資料;

View 代表檢視層,負責在頁面上展示資料;

ViewModel 是的作用是同步 View 和 Model 之間的

關聯,其實現同步關聯的核心是DOM ListenersData Bindings兩個工具。DOMListeners 工具用於監聽 View 中 DOM 的變化,並會選擇性的傳給 Model;Data Bindings 工具用於監聽 Model 資料變化,並將其更新給 View。



3. Vue 中元件之間傳值的方法有哪些?

父元件向子元件傳值

(1)父元件在子元件標籤中繫結自定義屬性

(2)子元件通過 props 屬性進行接收。

//父元件 
export default { components:{ Child } }
<Child :name="123" />

//子元件 
export default { props: ["name"]//此處亦可指定資料型別 }

子元件向父元件傳值:

(1)在父元件在子元件標籤中繫結自定義事件

(2)子元件通過this.$emit()方法觸發自定義事件,傳值給父元件。

//父元件 
export default { components:{ Child }, data:{ name:"123" }, methods:{ changeName(value){
this.name = value } } }
<Child @changeName="changeName" />

//子元件 
export default { methods:{ changeParentName:(value)=>{ this.$emit("changeName","456") } } }
<button @click="changeParentName">改變父元件的name</button>

兄弟元件之間傳值:

(1)共同傳給父元件,再由父元件分發(狀態提升);

(2)使用Vuex

(3)利用bus 事件匯流排

let bus = new Vue() 
A元件:methods :{ 函式{bus.$emit(‘自定義事件名’,資料)} //傳送 
B元件:created(){bus.$on(‘A傳送過來的自定義事件名’,函式)} //進行資料接收

4. Vue 中常見的生命週期鉤子函式有哪些?

Vue 中常見的生命週期鉤子函式總共有八個:

(1)建立階段

BeforeCreate:該函式在 Vue 例項初始化後,元件建立、資料監測(data observer)、watch/event 事件配置前呼叫。此時不能訪問 dataref,Vue 例項物件上僅有生命週期函式及部分預設事件。
Created:該函式在 Vue 元件建立完成後呼叫。此時資料監測、事件配置已完成,data 物件已可訪問,但元件尚未被渲染成 HTML 模板,ref 仍為 undefined$el 尚不可用。

如此階段要對 DOM 進行操作,就應將操作放在 Vue.nextTick 的回撥函式中。因為此階段 DOM 尚未被渲染,無法執行 DOM 操作。Vue.nextTick 會在下次 DOM 更新迴圈結束之後執行延遲迴調,在修改資料之後可以獲取更新後的 DOM。

(2)掛載階段

BeforeMount:該函式在元件掛載前呼叫,此時 HTML 模板編譯已完成,虛擬 DOM 已存在,$el 為可用狀態,但 ref 仍不可用。

一般在此階段進行初始資料的獲取操作。

Mounted:該函式在元件掛載完成後呼叫。此時$el元素已被vm.$el替代,ref可進行操作。

一般在此階段進行非同步請求的傳送操作。mounted 不會保證所有的子元件也都一起被掛載。如果希望等到整個檢視都渲染完畢,可以在 mounted 內部使用 vm.$nextTick

(3)更新階段

BeforeUpdate:該函式在資料更新、虛擬 DOM 打補丁前呼叫。

此階段適合在更新之前訪問現有的 DOM,比如手動移除已新增的事件監聽器。

Updated:該函式在資料更新、虛擬 DOM 打補丁完成後呼叫。

(4)解除安裝階段

BeforeDestory:該函式在例項銷燬前呼叫,此時例項完全可用,ref 仍然存在。

一般在此階段進行效能優化操作,如清除定時器,防止記憶體洩露。

Destroyed:該函式在例項銷燬後呼叫,此時 Vue 裡的所有指令均被解綁,所有事件監聽器已被移除,ref 狀態為 undefined

元件銷燬時,先銷燬父元件,再銷燬子元件。

針對 keep-alive 元件還有兩個鉤子函式:

activated:在被 keep-alive 快取的元件啟用時呼叫。

deactivated:在被 keep-alive 快取的元件停用時呼叫。

還有一個錯誤處理捕獲函式:

errorCaptured:在捕獲到一個來自子孫元件的錯誤時呼叫。


5. 為什麼 Vue 元件中 data 必須是一個函式?

如果 data 是一個物件,當複用元件時,因為 data 都會指向同一個引用型別地址,其中一個元件的 data 一旦發生修改,則其他重用的元件中的 data 也會被一併修改。

如果 data 是一個返回物件的函式,因為每次重用元件時返回的都是一個新物件,引用地址不同,便不會出現如上問題。

6. Vue 中 v-if 和 v-show 有什麼區別?

v-if 在進行切換時,會直接對標籤進行建立或銷燬,不顯示的標籤不會載入在 DOM 樹中。v-show 在進行切換時,會對標籤的 display 屬性進行切換,通過 display 不顯示來隱藏元素。

一般來說,v-if 的效能開銷會比 v-show 大,切換頻繁的標籤更適合使用 v-show。

7. Vue 中 computed 和 watch 有什麼區別?

計算屬性 computed

(1)支援快取,只有依賴資料發生變化時,才會重新進行計算函式;

(2)計算屬性內不支援非同步操作

(3)計算屬性的函式中都有一個 get(預設具有,獲取計算屬性)和 set(手動新增,設定計算屬性)方法;

(4)計算屬性是自動監聽依賴值的變化,從而動態返回內容。

偵聽屬性 watch

(1)不支援快取,只要資料發生變化,就會執行偵聽函式;

(2)偵聽屬性內支援非同步操作

(3)偵聽屬性的值可以是一個物件,接收 handler 回撥,deep,immediate 三個屬性

(3)監聽是一個過程,在監聽的值變化時,可以觸發一個回撥,並做一些其他事情

watch: { 
	obj: { 
    	//handler接收兩個引數(newVal:新值,oldVal:舊值 
    	handler: function(newVal, oldVal){ 
    		console.log(newVal); 
		}, 
	deep: true,//設定為true時會監聽物件內部值的變化; 
	immediate: true//設定為true時會立即以表示式的當前值觸發回撥; 
	} 
}

使用 immediate 可以優化以下場景:元件建立的時候立即獲取一次列表的資料,同時監聽<input/>框,每當發生變化的時候重新獲取一次篩選後的列表。

//優化前 
created(){ 
	this.fetchPostList() 
	}, 
watch: { 
	searchInputValue(){ this.fetchPostList() } 
	}
//優化後 
watch: { 
	searchInputValue:{ handler: 'fetchPostList', immediate: true } 
	}

8. $nextTick 是什麼?

Vue 實現響應式並不是在資料發生後立即更新 DOM,使用 vm.$nextTick 是在下次 DOM 更新迴圈結束之後立即執行延遲迴調。在修改資料之後使用,則可以在回撥中獲取更新後的 DOM

9. v-for 中 key 的作用是什麼?

key 是 Vue 使用 v-for 渲染列表時的節點標識。使用了 key 之後,當列表項發生變化時,Vue 會基於 key 的變化而重新排列元素順序,並且移除 key 不存在的元素,提升執行效率

10. Vue 的雙向資料繫結原理是什麼?

Vue 採用資料劫持+訂閱釋出模式實現雙向繫結。通過 Object.defineProperty()方法來為元件中 data 的每個屬性新增 get 和 set 方法,在資料變動時,觸發 set 裡相應的監聽回撥函式,將變動資訊釋出給訂閱者。主要有以下步驟:

(1)元件初始化時:

a. 建立一個dep 物件作為觀察者(依賴收集、訂閱釋出的載體);

b. 通過Object.defineProperty()方法對 data 中的屬性及子屬性物件的屬性,新增 getter 和 setter 方法; 呼叫 getter 時,便去 dep 裡註冊函式。呼叫 setter 時,便去通知執行剛剛註冊的函式。


(2)元件掛載時:

a. compile解析模板指令,將其中的變數替換成資料。然後初始化渲染頁面檢視,並將每個指令對應的節點繫結上更新函式、監聽函式。後續一旦資料發生變化,便會更新頁面。頁面發生變化時也會相應釋出變動資訊;

b. 元件同時會定義一個watcher 類作為訂閱者,watcher 可以視作 dep 和元件之間的橋樑。其在例項化時會向 dep 中新增自己,同時自身又有一個 update 方法,待收到 dep 的變動通知時,便會呼叫自己的 update 方法,觸發 compile 中的相應函式完成更新。



11. 如何動態更新物件或陣列的值?

因為 Object.defineProperty()的限制,Vue 無法監聽到物件或陣列內部某個屬性值的變化,因此在直接設定以上兩類資料的值時,頁面不會實時更新。此時可以通過 this.$set 方法來解決:

//this.$set(要改變的陣列/物件,要改變的位置/key,要改成的value) this.$set(this.arr, 0, "OBKoro1");
// 改變陣列 this.$set(this.obj, "c", "OBKoro1"); // 改變物件

陣列原生方法造成的資料更新,可以被 Vue 監聽到。如 splice()push()pop()等。


12. 常用的事件修飾符有哪些?

.stop:阻止冒泡;

.prevent:阻止預設行為;

.self:僅繫結元素自身可觸發;

.once:只觸發一次..

13. Vue 如何獲取 DOM 元素?

首先先為標籤元素設定 ref 屬性,然後通過 this.$refs.屬性值獲取。

<div ref="test"></div>

const dom = this.$refs.test

14. v-on 如何繫結多個事件?

可以通過 v-on 傳入物件來繫結多個事件:

<!--單事件繫結-->
<input type="text" @click="onClick">
<!--多事件繫結-->
<input type="text" v-on="{ input:onInput,focus:onFocus,blur:onBlur }">

15. Vue 初始化頁面閃動問題如何解決?

出現該問題是因為在 Vue 程式碼尚未被解析之前,尚無法控制頁面中 DOM 的顯示,所以會看見模板字串等程式碼。

解決方案是,在 css 程式碼中新增 v-cloak 規則,同時在待編譯的標籤上新增 v-cloak 屬性:

[v-cloak] { display: none; }

<div v-cloak>
  {{ message }}
</div>

16. Vue 如何清除瀏覽器快取?

(1)專案打包的時候給每個打包檔案加上 hash 值,一般是在檔案後面加上時間戳;

(2)在 html 檔案中加入 meta 標籤,content 屬性設定為no-cache;

(3) 在後端伺服器中進行禁止快取設定。

17. Vue-router 路由有哪些模式?

一般有兩種模式:

(1)hash 模式:後面的 hash 值的變化,瀏覽器既不會向伺服器發出請求,瀏覽器也不會重新整理,每次 hash 值的變化會觸發 hashchange 事件。

(2)history 模式:利用了 HTML5 中新增的 pushState() 和 replaceState() 方法。這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的 back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改時,雖然改變了當前的 URL,但瀏覽器不會立即向後端傳送請求。

18. Vue-cli 專案中每個資料夾和檔案的用處大致是什麼?

(1)bulid 資料夾:存放 webpack 的相關配置以及指令碼檔案,實際開發中一般用來配置 less、babel 和配置 webpack.base.config.js 檔案。

(2)config 資料夾:常用到此資料夾下的 config.js (index.js) 配置開發環境的埠號,是否開啟熱載入或者設定生產環境的靜態資源相對路徑、是否開啟 gzip 壓縮、npm run build 命令打包生成靜態資源的名稱和路徑等。

(3)node_modules 資料夾:存放 npm install 命令下載的開發環境和生產環境的各種依賴。

(4)src 資料夾 :存放元件原始碼、圖片樣式資源、入口檔案、路由配置等。

19. Vue-cli 專案中 assets 和 static 資料夾有什麼區別?

兩者都是用於存放專案中所使用的靜態資原始檔的資料夾。其區別在於:

** assets 中的檔案在執行 npm run build 的時候會打包,簡單來說就是會被壓縮體積,程式碼格式化之類的。打包之後也會放到 static 中。static 中的檔案則不會被打包**。

將圖片等未處理的檔案放在assets中,打包減少體積。而對於第三方引入的一些資原始檔如iconfont.css等可以放在static中,因為這些檔案已經經過處理了。

20. Vuex 是什麼?有哪幾種屬性?

Vuex 是專為Vue設計的狀態管理工具,採用集中式儲存管理 Vue 中所有元件的狀態。

(1)state屬性:基本資料

(2)getters屬性:從 state 中派生出的資料

(3)mutation屬性:更新 store 中資料的唯一途徑,其接收一個以 state 為第一引數的回撥函式;

const store = new Vuex.Store({
  state: {
    count: 1,
  },
  mutations: {
    increment(state) {
      // 變更狀態
      state.count++;
    },
  },
});

(4)action 屬性提交 mutation 以更改 state,其中可以包含非同步操作

const store = new Vuex.Store({
  state: {
    count: 0,
  },
  mutations: {
    increment(state) {
      state.count++;
    },
  },
  actions: {
    increment2(context) {
      context.commit('increment');
    },
    fun(context) {
      context.dispatch('increment2');
    },
  },
});

(5)module 屬性:用於將 store分割成不同的模組

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態