Vue 面試題總結
1. Vue 框架的優點是什麼?
(1)輕量級框架:只關注檢視層,大小隻有幾十Kb;
(2)簡單易學:文件通順清晰,語法簡單;
(3)資料雙向繫結,資料檢視結構分離,僅需操作資料即可完成頁面相應的更新;
(4)元件化開發:工程結構清晰,程式碼維護方便;
(5)虛擬 DOM載入 HTML 節點,執行效率高。
2. 什麼是 MVVM?
MVVM 是Model-View-ModelView的縮寫,是一種脫胎於 MVC 模式的設計模式。
Model 代表資料層,負責存放業務相關的資料;
View 代表檢視層,負責在頁面上展示資料;
ViewModel 是的作用是同步 View 和 Model 之間的DOM Listeners
和 Data 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
事件配置前呼叫。此時不能訪問 data
、ref
,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 的狀態