1. 程式人生 > >2019前端面試系列——Vue面試題

2019前端面試系列——Vue面試題

Vue 雙向繫結原理

       mvvm 雙向繫結,採用資料劫持結合釋出者-訂閱者模式的方式,通過 Object.defineProperty()來劫持各個屬性的 setter、getter,在資料變動時釋出訊息給訂閱者,觸發相應的監聽回撥。

幾個要點:
1、實現一個數據監聽器 Observer,能夠對資料物件的所有屬性進行監聽,如有變動可拿到最新值並通知訂閱者
2、實現一個指令解析器 Compile,對每個元素節點的指令進行掃描和解析,根據指令模板替換資料,以及繫結相應的更新函式
3、實現一個 Watcher,作為連線 Observer 和 Compile 的橋樑,能夠訂閱並收到每個屬性變動的通知,執行指令繫結的相應回撥函式,從而更新檢視

4、mvvm 入口函式,整合以上三者

具體步驟:

  1. 需要 observe 的資料物件進行遞迴遍歷,包括子屬性物件的屬性,都加上 setter 和 getter
    這樣的話,給這個物件的某個值賦值,就會觸發 setter,那麼就能監聽到了資料變化
  2. compile 解析模板指令,將模板中的變數替換成資料,然後初始化渲染頁面檢視,並將每個指令對應的節點繫結更新函式,新增監聽資料的訂閱者,一旦資料有變動,收到通知,更新檢視
  3. Watcher 訂閱者是 Observer 和 Compile 之間通訊的橋樑,主要做的事情是:
    • 在自身例項化時往屬性訂閱器(dep)裡面新增自己
    • 自身必須有一個 update() 方法
    • 待屬性變動 dep.notice() 通知時,能呼叫自身的 update() 方法,並觸發 Compile 中繫結的回撥,則功成身退。
  4. MVVM 作為資料繫結的入口,整合 Observer、Compile 和 Watcher 三者,通過Observer來監聽自己的 model 資料變化,通過 Compile 來解析編譯模板指令,最終利用 Watcher 搭起 Observer 和 Compile 之間的通訊橋樑,達到資料變化 -> 檢視更新;檢視互動變化(input) -> 資料 model 變更的雙向繫結效果。

描述下 vue 從初始化頁面--修改資料--重新整理頁面 UI 的過程?

      當 Vue 進入初始化階段時,一方面 Vue 會遍歷 data 中的屬性,並用 Object.defineProperty 將它轉化成 getter/setter 的形式,實現資料劫持(暫不談 Vue3.0 的 Proxy);另一方面,Vue 的指令編譯器 Compiler 對元素節點的各個指令進行解析,初始化檢視,並訂閱 Watcher 來更新試圖,此時 Watcher 會將自己新增到訊息訂閱器 Dep 中,此時初始化完畢。
      當資料發生變化時,觸發 Observer 中 setter 方法,立即呼叫 Dep.notify(),Dep 這個陣列開始遍歷所有的訂閱者,並呼叫其 update 方法,Vue 內部再通過 diff 演算法,patch 相應的更新完成對訂閱者檢視的改變。

Vue 的生命週期

vue生命週期詳解

  1. beforeCreatecreated
  2. beforeMountmounted
  3. beforeUpdateupdated
  4. beforeDestorydestoryed
  5. activateddeactivated

Vue 元件間通訊有哪些方式

Vue 元件間通訊六種方式

  1. props/$emit
  2. $emit/$on
  3. vuex
  4. $attrs/$listeners
  5. provide/inject
  6. $parent/$children 與 ref

watch、methods 和 計算屬性的區別

  • watch 為了監聽某個響應資料的變化。計算屬性是自動監聽依賴值的變化,從而動態返回內容,主要目的是簡化模板內的複雜運算。所以區別來源於用法,只是需要動態值,那就用計算屬性;需要知道值的改變後執行業務邏輯,才用 watch。
  • methods是一個方法,它可以接受引數,而computed 不能,computed 是可以快取的,methods 不會。computed 可以依賴其他 computed,甚至是其他元件的 data。

vue中怎麼重置data

使用Object.assign(),vm.$data可以獲取當前狀態下的data,vm.$options.data可以獲取到元件初始化狀態下的data。

Object.assign(this.$data, this.$options.data())

元件中寫 name 選項有什麼作用?

  1. 專案使用 keep-alive 時,可搭配元件 name 進行快取過濾
  2. DOM 做遞迴元件時需要呼叫自身 name
  3. vue-devtools 除錯工具裡顯示的組見名稱是由vue中元件name決定的

vue-router 有哪些鉤子函式

官方文件:vue-router鉤子函式

  • 全域性前置守衛 router.beforeEach
  • 全域性解析守衛 router.beforeResolve
  • 全域性後置鉤子 router.afterEach
  • 路由獨享的守衛 beforeEnter
  • 元件內的守衛 beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave

前端路由簡介以及vue-router實現原理

routerouter 的區別是什麼?

route是“路由資訊物件”,包括path,params,hash,query,fullPath,matched,name等路由資訊引數。
router是“路由例項物件”,包括了路由的跳轉方法(pushreplace),鉤子函式等。

說一下 Vue 和 React 的認識,做一個簡單的對比

1.監聽資料變化的實現原理不同

  • Vue 通過 getter/setter 以及一些函式的劫持,能精確快速的計算出 Virtual DOM 的差異。這是由於它在渲染過程中,會跟蹤每一個元件的依賴關係,不需要重新渲染整個元件樹。
  • React 預設是通過比較引用的方式進行的,如果不優化,每當應用的狀態被改變時,全部子元件都會重新渲染,可能導致大量不必要的 VDOM 的重新渲染。

      Vue 不需要特別的優化就能達到很好的效能,而對於 React 而言,需要通過 PureComponent/shouldComponentUpdate 這個生命週期方法來進行控制。如果你的應用中,互動複雜,需要處理大量的 UI 變化,那麼使用 Virtual DOM 是一個好主意。如果你更新元素並不頻繁,那麼 Virtual DOM 並不一定適用,效能很可能還不如直接操控 DOM。

      為什麼 React 不精確監聽資料變化呢?這是因為 Vue 和 React 設計理念上的區別,Vue 使用的是可變資料,而 React 更強調資料的不可變。

2.資料流的不同

  • Vue 中預設支援雙向繫結,元件與 DOM 之間可以通過 v-model 雙向繫結。但是,父子元件之間,props 在 2.x 版本是單向資料流
  • React 一直提倡的是單向資料流,他稱之為 onChange/setState()模式。

      不過由於我們一般都會用 Vuex 以及 Redux 等單向資料流的狀態管理框架,因此很多時候我們感受不到這一點的區別了。

3.模板渲染方式的不同

在表層上, 模板的語法不同

  • React 是通過 JSX 渲染模板
  • 而 Vue 是通過一種拓展的 HTML 語法進行渲染

在深層上,模板的原理不同,這才是他們的本質區別:

  • React 是在元件 JS 程式碼中,通過原生 JS 實現模板中的常見語法,比如插值,條件,迴圈等,都是通過 JS 語法實現的
  • Vue 是在和元件 JS 程式碼分離的單獨的模板中,通過指令來實現的,比如條件語句就需要 v-if 來實現

      對這一點,我個人比較喜歡 React 的做法,因為他更加純粹更加原生,而 Vue 的做法顯得有些獨特,會把 HTML 弄得很亂。舉個例子,說明 React 的好處:react 中 render 函式是支援閉包特性的,所以我們 import 的元件在 render 中可以直接呼叫。但是在 Vue 中,由於模板中使用的資料都必須掛在 this 上進行一次中轉,所以我們 import 一個元件完了之後,還需要在 components 中再宣告下,這樣顯然是很奇怪但又不得不這樣的做法。

Vue 的 nextTick 的原理是什麼?

1. 為什麼需要 nextTick
      Vue 是非同步修改 DOM 的並且不鼓勵開發者直接接觸 DOM,但有時候業務需要必須對資料更改--重新整理後的 DOM 做相應的處理,這時候就可以使用 Vue.nextTick(callback)這個 api 了。

2. 理解原理前的準備
      首先需要知道事件迴圈中巨集任務和微任務這兩個概念(這其實也是面試常考點)。請閱大佬文章--徹底搞懂瀏覽器 Event-loop
常見的巨集任務有 script, setTimeout, setInterval, setImmediate, I/O, UI rendering
常見的微任務有 process.nextTick(Nodejs),Promise.then(), MutationObserver;

3. 理解 nextTick
      而 nextTick 的原理正是 vue 通過非同步佇列控制 DOM 更新和 nextTick 回撥函式先後執行的方式。如果大家看過這部分的原始碼,會發現其中做了很多 isNative()的判斷,因為這裡還存在相容性優雅降級的問題。可見 Vue 開發團隊的深思熟慮,對效能的良苦用心。
如果你比較瞭解了前面的事件迴圈原理,推薦你看看這篇文章 請閱大佬文章--全面解析 Vue.nextTick 實現原理

Vuex有哪幾種屬性

有五種,分別是 StateGetterMutationActionModule

vue-cli 替我們做了哪些工作?

      首先需要知道 vue-cli 是什麼?它是基於 Vue.js 進行快速開發的完整系統,也可以理解成是很多 npm 包的集合。其次,vue-cli 完成的功能有哪些?

.vue 檔案 --> .js 檔案
ES6 語法 --> ES5 語法
Sass,Less,Stylus --> CSS
對 jpg,png,font 等靜態資源的處理
熱更新
定義環境變數,區分 dev 和 production 模式
...

如果開發者需要補充或修改預設設定,需要在 package.json 同級下新建一個 vue.config.js 檔案

最後送上一份大禮:vue 248個知識點(面試題)為你保駕護