Vue最全知識點

Vue最全知識點,面試必備(基礎到進階,覆蓋vue3.0,持續更新整理,歡迎補充討論)

參考文章傳送:1.童歐巴對vue知識的整理 2.我是你的超級英雄對vue知識的整理 3.vue官網

基礎篇

說說你對MVVM的理解

  • Model-View-ViewModel的縮寫,Model代表數據模型,View代表UI組件,ViewModel將Model和View關聯起來
  • 數據會綁定到viewModel層并自動將數據渲染到頁面中,視圖變化的時候會通知viewModel層更新數據

了解mvc/mvp/mvvm的區別

Vue2.x響應式數據/雙向綁定原理

  • Vue 數據雙向綁定主要是指:數據變化更新視圖,視圖變化更新數據。其中,View變化更新Data,可以通過事件監聽的方式來實現,所以 Vue數據雙向綁定的工作主要是如何根據Data變化更新View

  • 簡述

    • 當你把一個普通的 JavaScript 對象傳入 Vue 實例作為 data 選項,Vue 將遍歷此對象所有的 property,并使用 Object.defineProperty 把這些 property 全部轉為 getter/setter。
    • 這些 getter/setter 對用戶來說是不可見的,但是在內部它們讓 Vue 能夠追蹤依賴,在 property 被訪問和修改時通知變更。
    • 每個組件實例都對應一個 watcher 實例,它會在組件渲染的過程中把“接觸”過的數據 property 記錄為依賴。之后當依賴項的 setter 觸發時,會通知 watcher,從而使它關聯的組件重新渲染。

[圖片上傳失敗...(image-75cc09-1601173469405)]

  • 深入理解:

    • 監聽器 Observer:對數據對象進行遍歷,包括子屬性對象的屬性,利用 Object.defineProperty() 對屬性都加上 setter 和 getter。這樣的話,給這個對象的某個值賦值,就會觸發 setter,那么就能監聽到了數據變化。
    • 解析器 Compile:解析 Vue 模板指令,將模板中的變量都替換成數據,然后初始化渲染頁面視圖,并將每個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變動,收到通知,調用更新函數進行數據更新。
    • 訂閱者 Watcher:Watcher 訂閱者是 Observer 和 Compile 之間通信的橋梁 ,主要的任務是訂閱 Observer 中的屬性值變化的消息,當收到屬性值變化的消息時,觸發解析器 Compile 中對應的更新函數。每個組件實例都有相應的 watcher 實例對象,它會在組件渲染的過程中把屬性記錄為依賴,之后當依賴項的 setter 被調用時,會通知 watcher 重新計算,從而致使它關聯的組件得以更新——這是一個典型的觀察者模式
    • 訂閱器 Dep:訂閱器采用 發布-訂閱 設計模式,用來收集訂閱者 Watcher,對監聽器 Observer 和 訂閱者 Watcher 進行統一管理。

你知道Vue3.x響應式數據原理嗎?

  • Vue3.x改用Proxy替代Object.defineProperty

  • 因為Proxy可以直接監聽對象和數組的變化,并且有多達13種攔截方法。并且作為新標準將受到瀏覽器廠商重點持續的性能優化。

  • Proxy只會代理對象的第一層,Vue3是怎樣處理這個問題的呢?

    • 判斷當前Reflect.get的返回值是否為Object,如果是則再通過reactive方法做代理, 這樣就實現了深度觀測。
    • 監測數組的時候可能觸發多次get/set,那么如何防止觸發多次呢?我們可以判斷key是否為當前被代理對象target自身屬性,也可以判斷舊值與新值是否相等,只有滿足以上兩個條件之一時,才有可能執行trigger。

Proxy 與 Object.defineProperty 優劣對比

  • Proxy 的優勢如下:

    • Proxy 可以直接監聽對象而非屬性;
  • Proxy 可以直接監聽數組的變化;

    • Proxy 有多達 13 種攔截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具備的;
    • Proxy 返回的是一個新對象,我們可以只操作新的對象達到目的,而 Object.defineProperty 只能遍歷對象屬性直接修改;
    • Proxy 作為新標準將受到瀏覽器廠商重點持續的性能優化,也就是傳說中的新標準的性能紅利;
  • Object.defineProperty 的優勢如下:

    • 兼容性好,支持 IE9,而 Proxy 的存在瀏覽器兼容性問題,而且無法用 polyfill 磨平,因此 Vue 的作者才聲明需要等到下個大版本( 3.0 )才能用 Proxy 重寫。

VUEX篇

Vuex 是什么?

運用到了js設計模式中的單例模式,單例模式想要做到的是,不管我們嘗試去創建多少次,它都只給你返回第一次所創建的那唯一的一個實例。

  • Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。每一個 Vuex 應用的核心就是 store(倉庫)。“store” 基本上就是一個容器,它包含著你的應用中大部分的狀態 ( state )。

    • Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那么相應的組件也會相應地得到高效更新。
    • 改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化。

Vuex 使用單一狀態樹,用一個對象就包含了全部的應用層級狀態。至此它便作為一個“唯一數據源 (SSOT)”而存在。這也意味著,每個應用將僅僅包含一個 store 實例。單一狀態樹讓我們能夠直接地定位任一特定的狀態片段,在調試的過程中也能輕易地取得整個當前應用狀態的快照。 ——Vuex官方文檔

  • 主要包括以下幾個模塊:

    • State:定義了應用狀態的數據結構,可以在這里設置默認的初始狀態。
    • Getter:允許組件從 Store 中獲取數據,mapGetters 輔助函數僅僅是將 store 中的 getter 映射到局部計算屬性。
    • Mutation:是唯一更改 store 中狀態的方法,且必須是同步函數。
    • Action:用于提交 mutation,而不是直接變更狀態,可以包含任意異步操作。
    • Module:允許將單一的 Store 拆分為多個 store 且同時保存在單一的狀態樹中。

什么情況下使用 Vuex?

  • 如果應用夠簡單,最好不要使用 Vuex,一個簡單的 store 模式即可
  • 需要構建一個中大型單頁應用時,使用Vuex能更好地在組件外部管理狀態

Vuex和單純的全局對象有什么區別?

  • Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那么相應的組件也會相應地得到高效更新。
  • 不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地了解我們的應用。

為什么 Vuex 的 mutation 中不能做異步操作?

  • Vuex中所有的狀態更新的唯一途徑都是mutation,異步操作通過 Action 來提交 mutation實現,這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地了解我們的應用。
  • 每個mutation執行完成后都會對應到一個新的狀態變更,這樣devtools就可以打個快照存下來,然后就可以實現 time-travel 了。如果mutation支持異步操作,就沒有辦法知道狀態是何時更新的,無法很好的進行狀態的追蹤,給調試帶來困難。

新增:vuex的action有返回值嗎?返回的是什么?

  • store.dispatch 可以處理被觸發的 action 的處理函數返回的 Promise,并且 store.dispatch 仍舊返回 Promise
  • Action 通常是異步的,要知道 action 什么時候結束或者組合多個 action以處理更加復雜的異步流程,可以通過定義action時返回一個promise對象,就可以在派發action的時候就可以通過處理返回的 Promise處理異步流程

一個 store.dispatch 在不同模塊中可以觸發多個 action 函數。在這種情況下,只有當所有觸發函數完成后,返回的 Promise 才會執行。

新增:為什么不直接分發mutation,而要通過分發action之后提交 mutation變更狀態

  • mutation 必須同步執行,我們可以在 action 內部執行異步操作
  • 可以進行一系列的異步操作,并且通過提交 mutation 來記錄 action 產生的副作用(即狀態變更)

常規篇

computed 和 watch 的區別和運用的場景?

  • computed:是計算屬性,依賴其它屬性值,并且 computed 的值有緩存,只有它依賴的屬性值發生改變,下一次獲取 computed 的值時才會重新計算 computed 的值;

  • watch:沒有緩存性,更多的是「觀察」的作用,類似于某些數據的監聽回調 ,每當監聽的數據變化時都會執行回調進行后續操作;當我們需要深度監聽對象中的屬性時,可以打開deep:true選項,這樣便會對對象中的每一項進行監聽

  • 運用場景

    • 當我們需要進行數值計算,并且依賴于其它數據時,應該使用 computed,因為可以利用 computed 的緩存特性,避免每次獲取值時,都要重新計算;
    • 當我們需要在數據變化時執行異步或開銷較大的操作時,應該使用 watch,使用watch選項允許我們執行異步操作 ( 訪問一個 API ),限制我們執行該操作的頻率,并在我們得到最終結果前,設置中間狀態。這些都是計算屬性無法做到的。

Vue2.x組件通信有哪些方式?

  • 父子組件通信

    • 事件機制(**父->子props,子->父 $on、$emit)
    • 獲取父子組件實例 $parent、$children
    • Ref 獲取實例的方式調用組件的屬性或者方法
    • Provide、inject (不推薦使用,組件庫時很常用)
  • 兄弟組件通信

    • eventBus 這種方法通過一個空的 Vue實例作為中央事件總線(事件中心),用它來觸發事件和監聽事件,從而實現任何組件間的通信,包括父子、隔代、兄弟組件

    Vue.prototype.$bus = new Vue

    • Vuex
  • 跨級組件通信

    • Vuex
    • $attrs、$listeners
    • Provide、inject

說一下v-if和v-show的區別

  • 當條件不成立時,v-if不會渲染DOM元素,v-show操作的是樣式(display),切換當前DOM的顯示和隱藏。
  • v-if 適用于在運行時很少改變條件,不需要頻繁切換條件的場景;
  • v-show 則適用于需要非常頻繁切換條件的場景。

為什么 v-for 和 v-if 不建議用在一起

  • 當 v-for 和 v-if 處于同一個節點時,v-for 的優先級比 v-if 更高,這意味著 v-if 將分別重復運行于每個 v-for 循環中。如果要遍歷的數組很大,而真正要展示的數據很少時,這將造成很大的性能浪費
  • 這種場景建議使用 computed,先對數據進行過濾

組件中的data為什么是一個函數?

  • 一個組件被復用多次的話,也就會創建多個實例。本質上,這些實例用的都是同一個構造函數。
  • 如果data是對象的話,對象屬于引用類型,會影響到所有的實例。所以為了保證組件不同的實例之間data不沖突,data必須是一個函數。

子組件為什么不可以修改父組件傳遞的Prop?/怎么理解vue的單向數據流?

  • Vue提倡單向數據流,即父級props的更新會流向子組件,但是反過來則不行。
  • 這是為了防止意外的改變父組件狀態,使得應用的數據流變得難以理解。
  • 如果破壞了單向數據流,當應用復雜時,debug 的成本會非常高。

v-model是如何實現雙向綁定的?

  • v-model是用來在表單控件或者組件上創建雙向綁定的
  • 他的本質是v-bind和v-on的語法糖
  • 在一個組件上使用v-model,默認會為組件綁定名為value的prop和名為input的事件

nextTick的實現原理是什么?

  • 在下次 DOM 更新循環結束之后執行延遲回調,在修改數據之后立即使用 nextTick 來獲取更新后的 DOM。
  • nextTick主要使用了宏任務微任務
  • 根據執行環境分別嘗試采用Promise、MutationObserver、setImmediate,如果以上都不行則采用setTimeout定義了一個異步方法,多次調用nextTick會將方法存入隊列中,通過這個異步方法清空當前隊列。

Vue不能檢測數組的哪些變動?Vue 怎么用 vm.$set() 解決對象新增屬性不能響應的問題 ?

  • Vue 不能檢測以下數組的變動:

    • 當你利用索引直接設置一個數組項時,例如:vm.items[indexOfItem] = newValue

    • 當你修改數組的長度時,例如:vm.items.length = newLength

    • 解決辦法:

      • 第一類問題
// 法一:Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// 法二:Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
  • 第二類問題,可使用 splice:
vm.items.splice(newLength)
  • vm.$set 的實現原理是:

    • 如果目標是數組,直接使用數組的 splice 方法觸發相應式;
    • 如果目標是對象,會先判讀屬性是否存在、對象是否是響應式,最終如果要對屬性進行響應式處理,則是通過調用 defineReactive 方法進行響應式處理( defineReactive 方法就是 Vue 在初始化對象時,給對象屬性采用 Object.defineProperty 動態添加 getter 和 setter 的功能所調用的方法)

Vue事件綁定原理是什么?

  • 原生事件綁定是通過addEventListener綁定給真實元素的,組件事件綁定是通過Vue自定義的$on實現的。

說一下虛擬Dom以及key屬性的作用

  • 由于在瀏覽器中操作DOM是很昂貴的。頻繁的操作DOM,會產生一定的性能問題。這就是虛擬Dom的產生原因。

  • Virtual DOM本質就是用一個原生的JS對象去描述一個DOM節點。是對真實DOM的一層抽象。(也就是源碼中的VNode類,它定義在src/core/vdom/vnode.js中。)

  • 虛擬 DOM 的實現原理主要包括以下 3 部分:

    • 用 JavaScript 對象模擬真實 DOM 樹,對真實 DOM 進行抽象;
    • diff 算法 — 比較兩棵虛擬 DOM 樹的差異;
    • pach 算法 — 將兩個虛擬 DOM 對象的差異應用到真正的 DOM 樹。
  • key 是為 Vue 中 vnode 的唯一標記,通過這個 key,我們的 diff 操作可以更準確、更快速

    • 更準確:因為帶 key 就不是就地復用了,在 sameNode 函數a.key === b.key對比中可以避免就地復用的情況。所以會更加準確。
    • 更快速:利用 key 的唯一性生成 map 對象來獲取對應節點,比遍歷方式更快

為什么不建議用index作為key?

  • 不建議 用index 作為 key,和沒寫基本上沒區別,因為不管你數組的順序怎么顛倒,index 都是 0, 1, 2 這樣排列,導致 Vue 會復用錯誤的舊子節點,做很多額外的工作

生命周期篇

說一下你對Vue的生命周期的理解

  • 簡單回答

    • beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。
    • keep-alive 有自己獨立的鉤子函數 activated 和 deactivated。
  • 復雜回答

|

生命周期

| 發生了什么 |
| --- | --- |
| beforeCreate | 在當前階段data、methods、computed以及watch上的數據和方法都不能被訪問 |
| created | 在實例創建完成后發生,當前階段已經完成了數據觀測,也就是可以使用數據,更改數據,在這里更改數據不會觸發updated函數。可以做一些初始數據的獲取,在當前階段無法與Dom進行交互,如果非要想,可以通過vm.$nextTick來訪問Dom |
| beforeMount | 發生在掛載之前,在這之前template模板已導入渲染函數編譯。而當前階段虛擬Dom已經創建完成,即將開始渲染。在此時也可以對數據進行更改,不會觸發updated |
| mounted | 在掛載完成后發生,在當前階段,真實的Dom掛載完畢數據完成雙向綁定可以訪問到Dom節點,使用$refs屬性對Dom進行操作 |
| beforeUpdate | 發生在更新之前,也就是響應式數據發生更新,虛擬dom重新渲染之前被觸發,你可以在當前階段進行更改數據,不會造成重渲染 |
| updated | 發生在更新完成之后,當前階段組件Dom已完成更新。要注意的是避免在此期間更改數據,因為這可能會導致無限循環的更新 |
| beforeDestroy | 發生在實例銷毀之前,在當前階段實例完全可以被使用,我們可以在這時進行善后收尾工作,比如清除計時器 |
| destroyed | 發生在實例銷毀之后,這個時候只剩下了dom空殼。組件已被拆解,數據綁定被卸除,監聽被移出,子實例也統統被銷毀 |
| activited keep-alive 專屬 | 組件被激活時調用 |
| deactivated keep-alive 專屬 | 組件被銷毀時調用 |

Vue中組件生命周期調用順序是什么樣的?

  • 組件的調用順序都是先父后子,渲染完成的順序是先子后父。
  • 組件的銷毀操作是先父后子,銷毀完成的順序是先子后父。

在什么階段才能訪問操作DOM?

在鉤子函數 mounted 被調用前,Vue 已經將編譯好的模板掛載到頁面上,所以在 mounted 中可以訪問操作 DOM。

你的接口請求一般放在哪個生命周期中?

  • 可以在鉤子函數 created、beforeMount、mounted 中進行調用,因為在這三個鉤子函數中,data 已經創建,可以將服務端端返回的數據進行賦值。

  • 但是推薦在 created 鉤子函數中調用異步請求,因為在 created 鉤子函數中調用異步請求有以下優點:

    • 能更快獲取到服務端數據,減少頁面loading 時間;
    • ssr不支持 beforeMount 、mounted 鉤子函數,所以放在 created 中有助于一致性;

路由篇

vue路由hash模式和history模式實現原理分別是什么,他們的區別是什么?

  • hash 模式:

    • 后面 hash 值的變化,不會導致瀏覽器向服務器發出請求,瀏覽器不發出請求,就不會刷新頁面

    • 通過監聽 hashchange 事件可以知道 hash 發生了哪些變化,然后根據 hash 變化來實現更新頁面部分內容的操作。
  • history 模式:

    • history 模式的實現,主要是 HTML5 標準發布的兩個 API,pushStatereplaceState,這兩個 API 可以在改變 url,但是不會發送請求。這樣就可以監聽 url 變化來實現更新頁面部分內容的操作
  • 區別

    • url 展示上,hash 模式有“#”,history 模式沒有
    • 刷新頁面時,hash 模式可以正常加載到 hash 值對應的頁面,而 history 沒有處理的話,會返回 404,一般需要后端將所有頁面都配置重定向到首頁路由
    • 兼容性,hash 可以支持低版本瀏覽器和 IE。

路由懶加載是什么意思?如何實現路由懶加載?

  • 路由懶加載的含義:把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應組件

  • 實現:結合 Vue 的異步組件和 Webpack 的代碼分割功能

      1. 可以將異步組件定義為返回一個 Promise 的工廠函數 (該函數返回的 Promise 應該 resolve 組件本身)
const Foo = () => Promise.resolve({ /* 組件定義對象 */ })
    1. 在 Webpack 2 中,我們可以使用動態 import語法來定義代碼分塊點 (split point)
import('./Foo.vue') // 返回 Promise
*   結合這兩者,這就是如何定義一個能夠被 Webpack 自動代碼分割的異步組件
const Foo = () => import('./Foo.vue')
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo } ]})
  • 使用命名 chunk,和webpack中的魔法注釋就可以把某個路由下的所有組件都打包在同個異步塊 (chunk) 中
chunkconst Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')

Vue-router 導航守衛有哪些

  • 全局前置/鉤子:beforeEach、beforeResolve、afterEach
  • 路由獨享的守衛:beforeEnter
  • 組件內的守衛:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

進階篇

說說vue和react的異同

    • 使用 Virtual DOM
    • 提供了響應式 (Reactive) 和組件化 (Composable) 的視圖組件。
    • 將注意力集中保持在核心庫,而將其他功能如路由和全局狀態管理交給相關的庫。
    • 在 React 應用中,當某個組件的狀態發生變化時,它會以該組件為根,重新渲染整個組件子樹(除非使用PureComponent/shouldComponentUpdate),在 Vue 應用中,組件的依賴是在渲染過程中自動追蹤的,所以系統能精確知曉哪個組件確實需要被重渲染
    • 在 React 中,一切都是 JavaScript。不僅僅是 HTML 可以用 JSX 來表達,現在的潮流也越來越多地將 CSS 也納入到 JavaScript 中來處理
    • Vue 的路由庫和狀態管理庫都是由官方維護支持且與核心庫同步更新的。React 則是選擇把這些問題交給社區維護,因此創建了一個更分散的生態系統,所以有更豐富的生態系統
    • Vue 提供了CLI 腳手架,能讓你通過交互式的腳手架引導非常容易地構建項目。你甚至可以使用它快速開發組件的原型。React 在這方面也提供了create-react-app,但是現在還存在一些局限性
    • React Native 能使你用相同的組件模型編寫有本地渲染能力的 APP,Vue 和Weex會進行官方合作,Weex 是阿里巴巴發起的跨平臺用戶界面開發框架,同時也正在 Apache 基金會進行項目孵化,另一個選擇是NativeScript-Vue,一個用 Vue.js 構建完全原生應用的NativeScript插件

什么是 mixin ?

  • Mixin 使我們能夠為 Vue 組件編寫可插拔和可重用的功能。
  • 如果你希望再多個組件之間重用一組組件選項,例如生命周期 hook、 方法等,則可以將其編寫為 mixin,并在組件中簡單的引用它。
  • 然后將 mixin 的內容合并到組件中。如果你要在 mixin 中定義生命周期 hook,那么它在執行時將優化于組件自已的 hook。

在 Vue 實例中編寫生命周期 hook 或其他 option/properties 時,為什么不使用箭頭函數 ?

  • 箭頭函數自已沒有定義 this 上下文中。
  • 當你在 Vue 程序中使用箭頭函數 ( => ) 時,this 關鍵字病不會綁定到 Vue 實例,因此會引發錯誤。所以強烈建議改用標準函數聲明。

Vue模版編譯原理知道嗎,能簡單說一下嗎?

簡單說,Vue的編譯過程就是將template轉化為render函數的過程。會經歷以下階段(生成AST樹/優化/codegen):

  • 首先解析模版,生成AST語法樹(一種用JavaScript對象的形式來描述整個模板)。 使用大量的正則表達式對模板進行解析,遇到標簽、文本的時候都會執行對應的鉤子進行相關處理。
  • Vue的數據是響應式的,但其實模板中并不是所有的數據都是響應式的。有一些數據首次渲染后就不會再變化,對應的DOM也不會變化。那么優化過程就是深度遍歷AST樹,按照相關條件對樹節點進行標記。這些被標記的節點(靜態節點)我們就可以跳過對它們的比對,對運行時的模板起到很大的優化作用。
  • 編譯的最后一步是將優化后的AST樹轉換為可執行的代碼。

diff算法說一下

  • 同級比較,再比較子節點
  • 先判斷一方有子節點一方沒有子節點的情況(如果新的children沒有子節點,將舊的子節點移除)
  • 比較都有子節點的情況(核心diff)
  • 遞歸比較子節點

說說你對keep-alive組件的了解

  • keep-alive 是 Vue 內置的一個組件,可以使被包含的組件保留狀態,避免重新渲染 ,其有以下特性:

    • 一般結合路由和動態組件一起使用,用于緩存組件;
    • 提供 include 和 exclude 屬性,兩者都支持字符串或正則表達式, include 表示只有名稱匹配的組件會被緩存,exclude 表示任何名稱匹配的組件都不會被緩存 ,其中 exclude 的優先級比 include 高;
    • 對應兩個鉤子函數 activated 和 deactivated ,當組件被激活時,觸發鉤子函數 activated,當組件被移除時,觸發鉤子函數 deactivated。

說說你對SSR的了解

  • SSR也就是服務端渲染,也就是將Vue在客戶端把標簽渲染成HTML的工作放在服務端完成,然后再把html直接返回給客戶端

  • SSR的優勢

    • 更好的SEO
    • 首屏加載速度更快
  • SSR的缺點

    • 開發條件會受到限制,服務器端渲染只支持beforeCreate和created兩個鉤子
    • 當我們需要一些外部擴展庫時需要特殊處理,服務端渲染應用程序也需要處于Node.js的運行環境
    • 更多的服務端負載

你都做過哪些Vue的性能優化?

  • 編碼階段

    • 盡量減少data中的數據,data中的數據都會增加getter和setter,會收集對應的watcher
    • v-if和v-for不能連用
    • 如果需要使用v-for給每項元素綁定事件時使用事件代理
    • SPA 頁面采用keep-alive緩存組件
    • 在更多的情況下,使用v-if替代v-show
    • key保證唯一
    • 使用路由懶加載、異步組件
    • 防抖、節流
    • 第三方模塊按需導入
    • 長列表滾動到可視區域動態加載
    • 圖片懶加載
  • SEO優化

    • 預渲染
    • 服務端渲染SSR
  • 打包優化

    • 壓縮代碼
    • Tree Shaking/Scope Hoisting
    • 使用cdn加載第三方模塊
    • 多線程打包happypack
    • splitChunks抽離公共文件
    • sourceMap優化
  • 用戶體驗

    • 骨架屏
    • PWA
    • 還可以使用緩存(客戶端緩存、服務端緩存)優化、服務端開啟gzip壓縮等。

vue2.x中如何監測數組變化?

  • 使用了函數劫持的方式,重寫了數組的方法,Vue將data中的數組進行了原型鏈重寫,指向了自己定義的數組原型方法,當調用數組api時,可以通知依賴更新。
  • 如果數組中包含著引用類型,會對數組中的引用類型再次遞歸遍歷進行監控。這樣就實現了監測數組變化。

說說你對 SPA 單頁面的理解,它的優缺點分別是什么?

  • SPA( single-page application )僅在 Web 頁面初始化時加載相應的 HTML、JavaScript 和 CSS。一旦頁面加載完成,SPA 不會因為用戶的操作而進行頁面的重新加載或跳轉;取而代之的是利用路由機制實現 HTML 內容的變換,UI 與用戶的交互,避免頁面的重新加載。

  • 優點:

    • 用戶體驗好、快,內容的改變不需要重新加載整個頁面,避免了不必要的跳轉和重復渲染;
    • 基于上面一點,SPA 相對對服務器壓力小;
    • 前后端職責分離,架構清晰,前端進行交互邏輯,后端負責數據處理;
  • 缺點:

    • 初次加載耗時多:為實現單頁 Web 應用功能及顯示效果,需要在加載頁面的時候將 JavaScript、CSS 統一加載,部分頁面按需加載;
    • 前進后退路由管理:由于單頁應用在一個頁面中顯示所有的內容,所以不能使用瀏覽器的前進后退功能,所有的頁面切換需要自己建立堆棧管理;
    • SEO 難度較大:由于所有的內容都在一個頁面中動態替換顯示,所以在 SEO 上其有著天然的弱勢。

對于即將到來的 vue3.0 特性你有什么了解的嗎?

  • 監測機制的改變

    • 3.0 將帶來基于代理 Proxy的 observer 實現,提供全語言覆蓋的反應性跟蹤。
    • 消除了 Vue 2 當中基于 Object.defineProperty 的實現所存在的很多限制:
  • 只能監測屬性,不能監測對象

    • 檢測屬性的添加和刪除;
    • 檢測數組索引和長度的變更;
    • 支持 Map、Set、WeakMap 和 WeakSet。
  • 模板

    • 模板方面沒有大的變更,只改了作用域插槽,2.x 的機制導致作用域插槽變了,父組件會重新渲染,而 3.0 把作用域插槽改成了函數的方式,這樣只會影響子組件的重新渲染,提升了渲染的性能。
    • 同時,對于 render 函數的方面,vue3.0 也會進行一系列更改來方便習慣直接使用 api 來生成 vdom 。
  • 對象式的組件聲明方式

    • vue2.x 中的組件是通過聲明的方式傳入一系列 option,和 TypeScript 的結合需要通過一些裝飾器的方式來做,雖然能實現功能,但是比較麻煩。
    • 3.0 修改了組件的聲明方式,改成了類式的寫法,這樣使得和 TypeScript 的結合變得很容易
  • 其它方面的更改

    • 支持自定義渲染器,從而使得 weex 可以通過自定義渲染器的方式來擴展,而不是直接 fork 源碼來改的方式。
    • 支持 Fragment(多個根節點)和 Protal(在 dom 其他部分渲染組建內容)組件,針對一些特殊的場景做了處理。
    • 基于 tree shaking 優化,提供了更多的內置功能。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370