1. 程式人生 > >【前端芝士樹】Vue.js面試題整理 / 知識點梳理

【前端芝士樹】Vue.js面試題整理 / 知識點梳理

【前端芝士樹】 Vue.js 面試題整理

MVVM是什麼?

MVVMModel-View-ViewModel 的縮寫。

  • Model代表資料模型,也可以在Model中定義資料修改和操作的業務邏輯。
  • View 代表UI 元件,它負責將資料模型轉化成UI 展現出來。
  • ViewModel 監聽模型資料的改變和控制檢視行為、處理使用者互動,簡單理解就是一個同步View 和 Model的物件,連線Model和View。

在MVVM架構下,View 和 Model 之間並沒有直接的聯絡,而是通過ViewModel進行互動,Model 和 ViewModel 之間的互動是雙向的, 因此View 資料的變化會同步到Model中,而Model 資料的變化也會立即反應到View 上。

ViewModel 通過雙向資料繫結把 View 層和 Model 層連線了起來,而View 和 Model 之間的同步工作完全是自動的,無需人為干涉,因此開發者只需關注業務邏輯,不需要手動操作DOM, 不需要關注資料狀態的同步問題,複雜的資料狀態維護完全由 MVVM 來統一管理。

在這裡插入圖片描述

注意, MVVM模型中, Model和View是不會直接連線的,而ViewModel則會以雙向連線的形式連線Model和View。

0. Vue的特性(優缺點)以及和其他框架的對比

Vue的優點

  1. 輕量級的框架
  2. 雙向資料繫結
  3. 指令
  4. 外掛化

與React的對比

節選自 Vue的官方文件
,筆者我進行了一些梳理,想了解得具體些的話還是猛戳連結吧。
  • 兩者具有許多的相似之處

    • 使用 Virtual DOM
    • 提供了響應式 (Reactive) 和元件化 (Composable) 的檢視元件。
    • 將注意力集中保持在核心庫,而將其他功能如路由和全域性狀態管理交給相關的庫。
  • Vue與React的不同之處

    • 元件的重渲染 React中元件的重渲染需要通過shouldComponentUpdate來避免不必要的子元件的重渲染,而Vue中元件的依賴是在渲染過程中自動追蹤的,所以系統能精確知曉哪個元件確實需要被重渲染。
    • JSX vs Template
      在 React 中,所有的元件的渲染功能都依靠 JSX。JSX 是使用 XML 語法編寫 JavaScript 的一種語法糖。Vue預設推薦使用Vue模板(更適用於表現類),但Vue也支援JSX。
    • 元件作用域的CSS 在React中,CSS 作用域是通過 CSS-in-JS 的方案實現的 (比如 styled-components、glamorous 和 emotion),而Vue則有更好的解決方案,如下:

      ``` <style scoped> @media (min-width: 250px) { .list-container:hover { background: orange; } } </style> ```

      這個可選 scoped 屬性會自動新增一個唯一的屬性 (比如 data-v-21e5b78) 為元件內 CSS 指定作用域,編譯的時候 .list-container:hover 會被編譯成類似 .list-container[data-v-21e5b78]:hover,這樣就可以控制CSS只在這個元件內生效。

1. Vue的生命週期

具體可以參照官網的這張圖,左側以紅色框表示的都是階段

  1. beforeCreate
  2. created
  3. beforeMount
  4. mounted
  5. beforeUpdated
  6. updated
  7. beforeDestroy
  8. destroyed

大致過程就是

  • 資料初始化(1~2)
    完成資料觀測、屬性和方法的運算載入,event/wather時間回撥。
  • dom掛載階段(3~4)
    el被新建立的vm.$el替換並掛載到例項上去,之後呼叫鉤子函式。
  • 資料更新階段(5~6)
    資料更新,虛擬dom重渲染
  • 元件解除安裝階段(7~8)
    銷燬例項及子例項

2. Vue實現資料雙向繫結的原理

vue實現資料雙向繫結主要是採用資料劫持結合釋出者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在資料變動時釋出訊息給訂閱者,觸發相應監聽回撥。當把一個普通 Javascript 物件傳給 Vue 例項來作為它的 data 選項時,Vue 將遍歷它的屬性,用 Object.defineProperty 將它們轉為 getter/setter。使用者看不到 getter/setter,但是在內部它們讓 Vue 追蹤依賴,在屬性被訪問和修改時通知變化。

vue的資料雙向繫結 將MVVM作為資料繫結的入口,整合Observer,Compile和Watcher三者,通過Observer來監聽自己的model的資料變化,通過Compile來解析編譯模板指令,最終利用watcher搭起observer和Compile之間的通訊橋樑,達到資料變化 —>檢視更新;檢視互動變化(input)—>資料model變更雙向繫結效果。

3. Vue的路由實現

路由的實現有兩種:hash和history interface來實現前端路由,
hash在瀏覽器中符號“#”,#以及#後面的字元稱之為hash,用window.location.hash讀取;特點:

(1)hash雖然在URL中,但不被包括在HTTP請求中

(2)用來指導瀏覽器動作,對服務端安全無用,hash不會重載入頁面

history採用h5的新特性;且提供了兩個新方法:pushState(),replaceState()可以對瀏覽器歷史記錄棧進行修改,以及popState事件的監聽到狀態變更,不過history有個問題是:如果使用者直接在位址列中輸入並回車,瀏覽器重啟或重新載入時,history模式會將url修改的和正常請求後端一樣,此情況下,重新向後端傳送請求,後端如果沒有配置對應路由處理,則返回404,解決方法是後端配置一下。

4. Vue的路由傳參


&lt;router-link :to="{path:'/index',params:{id:num}}"&gt;
&lt;router-link :to="{ path:'/index' , query:{id:num}}"&gt;

然後通過$route.params來讀取資料,但路由傳遞引數值是物件的話就不行了會報錯,傳遞前用base64轉譯一下就可以了。

5. Vue元件間的引數傳遞

父元件與子元件傳值

父元件通過標籤上面定義傳值


&lt;parent&gt;
&lt;child :child-msg="msg"&gt;&lt;/child&gt;  //這裡必須要用 - 代替駝峰
&lt;/parent&gt;

data(){
   return {
       msg: [1,2,3]
   };
}

子元件通過props方法接受資料


子元件通過props來接收資料: 
方式1:
props: ['childMsg']

方式2 :
props: {
    childMsg: Array //這樣可以指定傳入的型別,如果型別不對,會警告
}

方式3:
props: {
    childMsg: {
        type: Array,    //傳入的型別
        default: [0,0,0] //這樣可以指定預設的值
    }
}

子元件向父元件傳遞資料

子元件通過$emit方法傳遞引數


&lt;template&gt;
    &lt;div @click="testClick"&gt;&lt;/div&gt;
&lt;/template&gt;

methods: {
    testClick() {
        this.$emit('test','123'); 
        //$emit(even,value)even 是一個函式,value 是傳給父元件的值 , 觸發名為test方法, '123'為向父元件傳遞的資料
    }
}

父元件通過v-on(簡寫為@)來監聽DOM事件,並在觸發時接收資料執行js函式。


&lt;div&gt;
    &lt;child @test="change" :msg="msg"&gt;&lt;/child&gt;  //監聽子元件觸發的test事件,然後呼叫change方法
&lt;/div&gt;
methods: {
    change(val) {
        this.msg = val;  // val: 123
    }
}

非父子元件間的資料傳遞

如果2個元件不是父子元件那麼如何通訊呢?這時可以通過eventHub來實現通訊.
所謂eventHub就是建立一個事件中心,相當於中轉站,可以用它來傳遞事件和接收事件.


let Hub = new Vue(); //建立事件中心

元件1觸發:


&lt;div @click="eve"&gt;&lt;/div&gt;
methods: {
    eve() {
        Hub.$emit('change','hehe'); //Hub觸發事件
    }
}

元件2接收:


&lt;div&gt;&lt;/div&gt;
created() {
    Hub.$on('change', () =&gt; { //Hub接收事件
        this.msg = 'hehe';
    });
}

6. Vue響應資料變化的幾種做法

  1. methods: 每次獲取都會重新計算求值
  2. computed(計算屬性,有快取): 基於資料依賴進行快取,只有當資料變化時,才會重新求值。(計算屬性只有 getter,可以在需要的時候自己設定 setter)。computed 擅長處理的情景:一個數據受多個數據影響。
  3. watch: 當需要在資料變化時執行非同步操作或者消耗較大的操作時,比較有效。watch 擅長處理的情景:一個數據影響多個數據。
  4. v-model: 基於資料雙向繫結(對於 v-for 迴圈列表中的項,需要使用鍵值)

7. Vue的條件渲染

Vue的條件渲染涉及到兩個不同的關鍵字 v-ifv-show

v-if

v-if 是真正的條件渲染,它會適當地銷燬和重建DOM達到讓元素顯示和隱藏的效果。
(Vue 會盡可能高效地渲染元素,通常會複用已有元素而不是從頭開始渲染,可以看一下第二段程式)
v-if 也是惰性的:如果在初始渲染時條件為假,則什麼也不做——直到條件第一次變為真時,才會開始渲染條件塊。


&lt;div v-if="type === 'A'"&gt;
  A
&lt;/div&gt;
&lt;div v-else-if="type === 'B'"&gt;
  B
&lt;/div&gt;
&lt;div v-else-if="type === 'C'"&gt;
  C
&lt;/div&gt;
&lt;div v-else&gt;
  Not A/B/C
&lt;/div&gt;

Vue 為你提供了一種方式來表達“這兩個元素是完全獨立的,不要複用它們”。
只需新增一個具有唯一值的 key 屬性即可,沒有 key 說明的話就會被複用:


&lt;template v-if="loginType === 'username'"&gt;
  &lt;label&gt;Username&lt;/label&gt;
  &lt;input placeholder="Enter your username" key="username-input"&gt;
&lt;/template&gt;
&lt;template v-else&gt;
  &lt;label&gt;Email&lt;/label&gt;
  &lt;input placeholder="Enter your email address" key="email-input"&gt;
&lt;/template&gt;

注意,<label> 元素仍然會被高效地複用,因為它們沒有新增 key 屬性。

v-show

通過修改元素的display的CSS屬性讓其顯示或者隱藏,元素始終會被渲染並保留在DOM中。


&lt;h1 v-show="ok"&gt;Hello!&lt;/h1&gt;
//ok 在data裡進行賦值為true或者false

v-if vs v-show

一般來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show 較好;如果在執行時條件很少改變,則使用 v-if 較好。

歡迎諸位同道們留言補充ヾ(◍°∇°◍)ノ゙

參考連結
Vue官方教程
MVVM - 廖雪峰的官方網站
MVC,MVP 和 MVVM 的圖示 - 阮一峰的網路日誌
vue.js學習筆記(一):什麼是mvvm框架,vue.js的核心思想 - _林沖 - 部落格園
vue父子元件通訊 - Hi-Sen - 部落格園
Vue 成長之路(一) - 媛媛碼農成長記 - SegmentFault 思否

來源:https://segmentfault.com/a/1190000016268245