2022必會(huì)的vue高頻面試題(附答案)

Vue-router 導(dǎo)航守衛(wèi)有哪些

  • 全局前置/鉤子:beforeEach巧勤、beforeResolve颅悉、afterEach
  • 路由獨(dú)享的守衛(wèi):beforeEnter
  • 組件內(nèi)的守衛(wèi):beforeRouteEnter、beforeRouteUpdate延曙、beforeRouteLeave

為什么在 Vue3.0 采用了 Proxy,拋棄了 Object.defineProperty搂鲫?

Object.defineProperty 本身有一定的監(jiān)控到數(shù)組下標(biāo)變化的能力,但是在 Vue 中,從性能/體驗(yàn)的性價(jià)比考慮,尤大大就棄用了這個(gè)特性(Vue 為什么不能檢測(cè)數(shù)組變動(dòng) )。為了解決這個(gè)問題,經(jīng)過 vue 內(nèi)部處理后可以使用以下幾種方法來(lái)監(jiān)聽數(shù)組

push();
pop();
shift();
unshift();
splice();
sort();
reverse();
復(fù)制代碼

由于只針對(duì)了以上 7 種方法進(jìn)行了 hack 處理,所以其他數(shù)組的屬性也是檢測(cè)不到的,還是具有一定的局限性拣挪。

Object.defineProperty 只能劫持對(duì)象的屬性,因此我們需要對(duì)每個(gè)對(duì)象的每個(gè)屬性進(jìn)行遍歷菠劝。Vue 2.x 里,是通過 遞歸 + 遍歷 data 對(duì)象來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)的監(jiān)控的,如果屬性值也是對(duì)象那么需要深度遍歷,顯然如果能劫持一個(gè)完整的對(duì)象是才是更好的選擇赶诊。

Proxy 可以劫持整個(gè)對(duì)象,并返回一個(gè)新的對(duì)象。Proxy 不僅可以代理對(duì)象,還可以代理數(shù)組锄码。還可以代理動(dòng)態(tài)增加的屬性晌涕。

v-for 為什么要加 key

如果不使用 key重窟,Vue 會(huì)使用一種最大限度減少動(dòng)態(tài)元素并且盡可能的嘗試就地修改/復(fù)用相同類型元素的算法巡扇。key 是為 Vue 中 vnode 的唯一標(biāo)記,通過這個(gè) key斋枢,我們的 diff 操作可以更準(zhǔn)確、更快速

更準(zhǔn)確:因?yàn)閹?key 就不是就地復(fù)用了涩赢,在 sameNode 函數(shù) a.key === b.key 對(duì)比中可以避免就地復(fù)用的情況怯邪。所以會(huì)更加準(zhǔn)確悬秉。

更快速:利用 key 的唯一性生成 map 對(duì)象來(lái)獲取對(duì)應(yīng)節(jié)點(diǎn)和泌,比遍歷方式更快

如何從真實(shí)DOM到虛擬DOM

涉及到Vue中的模板編譯原理武氓,主要過程:

  1. 將模板轉(zhuǎn)換成 ast 樹县恕, ast 用對(duì)象來(lái)描述真實(shí)的JS語(yǔ)法(將真實(shí)DOM轉(zhuǎn)換成虛擬DOM)
  2. 優(yōu)化樹
  3. ast 樹生成代碼

為什么Vue采用異步渲染呢?

Vue 是組件級(jí)更新况木,如果不采用異步更新火惊,那么每次更新數(shù)據(jù)都會(huì)對(duì)當(dāng)前組件進(jìn)行重新渲染屹耐,所以為了性能寿弱, Vue 會(huì)在本輪數(shù)據(jù)更新后症革,在異步更新視圖噪矛。核心思想 nextTick 艇挨。

dep.notify() 通知 watcher進(jìn)行更新缩滨, subs[i].update 依次調(diào)用 watcher 的 update 脉漏, queueWatcher 將watcher 去重放入隊(duì)列, nextTick( flushSchedulerQueue )在下一tick中刷新watcher隊(duì)列(異步)。

為什么vue組件中data必須是一個(gè)函數(shù)碉怔?

對(duì)象為引用類型撮胧,當(dāng)復(fù)用組件時(shí)芹啥,由于數(shù)據(jù)對(duì)象都指向同一個(gè)data對(duì)象,當(dāng)在一個(gè)組件中修改data時(shí)傀履,其他重用的組件中的data會(huì)同時(shí)被修改钓账;而使用返回對(duì)象的函數(shù)服协,由于每次返回的都是一個(gè)新對(duì)象(Object的實(shí)例)偿荷,引用地址不同,則不會(huì)出現(xiàn)這個(gè)問題泪蔫。

MVC 和 MVVM 區(qū)別

MVC

MVC 全名是 Model View Controller铣揉,是模型(model)-視圖(view)-控制器(controller)的縮寫餐曹,一種軟件設(shè)計(jì)典范

  • Model(模型):是應(yīng)用程序中用于處理應(yīng)用程序數(shù)據(jù)邏輯的部分朽合。通常模型對(duì)象負(fù)責(zé)在數(shù)據(jù)庫(kù)中存取數(shù)據(jù)
  • View(視圖):是應(yīng)用程序中處理數(shù)據(jù)顯示的部分饱狂。通常視圖是依據(jù)模型數(shù)據(jù)創(chuàng)建的
  • Controller(控制器):是應(yīng)用程序中處理用戶交互的部分曹步。通常控制器負(fù)責(zé)從視圖讀取數(shù)據(jù)休讳,控制用戶輸入讲婚,并向模型發(fā)送數(shù)據(jù)

MVC 的思想:一句話描述就是 Controller 負(fù)責(zé)將 Model 的數(shù)據(jù)用 View 顯示出來(lái),換句話說(shuō)就是在 Controller 里面把 Model 的數(shù)據(jù)賦值給 View俊柔。

MVVM

MVVM 新增了 VM 類

  • ViewModel 層:做了兩件事達(dá)到了數(shù)據(jù)的雙向綁定 一是將【模型】轉(zhuǎn)化成【視圖】筹麸,即將后端傳遞的數(shù)據(jù)轉(zhuǎn)化成所看到的頁(yè)面。實(shí)現(xiàn)的方式是:數(shù)據(jù)綁定雏婶。二是將【視圖】轉(zhuǎn)化成【模型】,即將所看到的頁(yè)面轉(zhuǎn)化成后端的數(shù)據(jù)。實(shí)現(xiàn)的方式是:DOM 事件監(jiān)聽。

MVVM 與 MVC 最大的區(qū)別就是:它實(shí)現(xiàn)了 View 和 Model 的自動(dòng)同步,也就是當(dāng) Model 的屬性改變時(shí)埋哟,我們不用再自己手動(dòng)操作 Dom 元素抛计,來(lái)改變 View 的顯示双饥,而是改變屬性后該屬性對(duì)應(yīng) View 層顯示會(huì)自動(dòng)改變(對(duì)應(yīng)Vue數(shù)據(jù)驅(qū)動(dòng)的思想)

整體看來(lái),MVVM 比 MVC 精簡(jiǎn)很多浸踩,不僅簡(jiǎn)化了業(yè)務(wù)與界面的依賴另假,還解決了數(shù)據(jù)頻繁更新的問題凌受,不用再用選擇器操作 DOM 元素腾么。因?yàn)樵?MVVM 中殴泰,View 不知道 Model 的存在,Model 和 ViewModel 也觀察不到 View术陶,這種低耦合模式提高代碼的可重用性

注意:Vue 并沒有完全遵循 MVVM 的思想 這一點(diǎn)官網(wǎng)自己也有說(shuō)明

那么問題來(lái)了 為什么官方要說(shuō) Vue 沒有完全遵循 MVVM 思想呢脓豪?

  • 嚴(yán)格的 MVVM 要求 View 不能和 Model 直接通信,而 Vue 提供了$refs 這個(gè)屬性,讓 Model 可以直接操作 View,違反了這一規(guī)定荤胁,所以說(shuō) Vue 沒有完全遵循 MVVM。

Vue 為什么要用 vm.$set() 解決對(duì)象新增屬性不能響應(yīng)的問題 秸讹?你能說(shuō)說(shuō)如下代碼的實(shí)現(xiàn)原理么?

1)Vue為什么要用vm.$set() 解決對(duì)象新增屬性不能響應(yīng)的問題

  1. Vue使用了Object.defineProperty實(shí)現(xiàn)雙向數(shù)據(jù)綁定
  2. 在初始化實(shí)例時(shí)對(duì)屬性執(zhí)行 getter/setter 轉(zhuǎn)化
  3. 屬性必須在data對(duì)象上存在才能讓Vue將它轉(zhuǎn)換為響應(yīng)式的(這也就造成了Vue無(wú)法檢測(cè)到對(duì)象屬性的添加或刪除)

所以Vue提供了Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value)

2)接下來(lái)我們看看框架本身是如何實(shí)現(xiàn)的呢?

Vue 源碼位置:vue/src/core/instance/index.js

export function set (target: Array<any> | Object, key: any, val: any): any {
  // target 為數(shù)組  
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    // 修改數(shù)組的長(zhǎng)度, 避免索引>數(shù)組長(zhǎng)度導(dǎo)致splcie()執(zhí)行有誤
    target.length = Math.max(target.length, key)
    // 利用數(shù)組的splice變異方法觸發(fā)響應(yīng)式  
    target.splice(key, 1, val)
    return val
  }
  // key 已經(jīng)存在,直接修改屬性值  
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  // target 本身就不是響應(yīng)式數(shù)據(jù), 直接賦值
  if (!ob) {
    target[key] = val
    return val
  }
  // 對(duì)屬性進(jìn)行響應(yīng)式處理
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val
}

我們閱讀以上源碼可知,vm.$set 的實(shí)現(xiàn)原理是:

  1. 如果目標(biāo)是數(shù)組,直接使用數(shù)組的 splice 方法觸發(fā)相應(yīng)式烛愧;
  2. 如果目標(biāo)是對(duì)象,會(huì)先判讀屬性是否存在宪摧、對(duì)象是否是響應(yīng)式,
  3. 最終如果要對(duì)屬性進(jìn)行響應(yīng)式處理,則是通過調(diào)用 defineReactive 方法進(jìn)行響應(yīng)式處理

defineReactive 方法就是 Vue 在初始化對(duì)象時(shí),給對(duì)象屬性采用 Object.defineProperty 動(dòng)態(tài)添加 getter 和 setter 的功能所調(diào)用的方法

Vue3.0 和 2.0 的響應(yīng)式原理區(qū)別

Vue3.x 改用 Proxy 替代 Object.defineProperty恨锚。因?yàn)?Proxy 可以直接監(jiān)聽對(duì)象和數(shù)組的變化,并且有多達(dá) 13 種攔截方法。

相關(guān)代碼如下

import { mutableHandlers } from "./baseHandlers"; // 代理相關(guān)邏輯
import { isObject } from "./util"; // 工具方法

export function reactive(target) {
  // 根據(jù)不同參數(shù)創(chuàng)建不同響應(yīng)式對(duì)象
  return createReactiveObject(target, mutableHandlers);
}
function createReactiveObject(target, baseHandler) {
  if (!isObject(target)) {
    return target;
  }
  const observed = new Proxy(target, baseHandler);
  return observed;
}

const get = createGetter();
const set = createSetter();

function createGetter() {
  return function get(target, key, receiver) {
    // 對(duì)獲取的值進(jìn)行放射
    const res = Reflect.get(target, key, receiver);
    console.log("屬性獲取", key);
    if (isObject(res)) {
      // 如果獲取的值是對(duì)象類型,則返回當(dāng)前對(duì)象的代理對(duì)象
      return reactive(res);
    }
    return res;
  };
}
function createSetter() {
  return function set(target, key, value, receiver) {
    const oldValue = target[key];
    const hadKey = hasOwn(target, key);
    const result = Reflect.set(target, key, value, receiver);
    if (!hadKey) {
      console.log("屬性新增", key, value);
    } else if (hasChanged(value, oldValue)) {
      console.log("屬性值被修改", key, value);
    }
    return result;
  };
}
export const mutableHandlers = {
  get, // 當(dāng)獲取屬性時(shí)調(diào)用此方法
  set, // 當(dāng)修改屬性時(shí)調(diào)用此方法
};

Vue模版編譯原理知道嗎,能簡(jiǎn)單說(shuō)一下嗎?

簡(jiǎn)單說(shuō)监徘,Vue的編譯過程就是將template轉(zhuǎn)化為render函數(shù)的過程。會(huì)經(jīng)歷以下階段:

  • 生成AST樹
  • 優(yōu)化
  • codegen

首先解析模版溅漾,生成AST語(yǔ)法樹(一種用JavaScript對(duì)象的形式來(lái)描述整個(gè)模板)山叮。 使用大量的正則表達(dá)式對(duì)模板進(jìn)行解析,遇到標(biāo)簽添履、文本的時(shí)候都會(huì)執(zhí)行對(duì)應(yīng)的鉤子進(jìn)行相關(guān)處理屁倔。

Vue的數(shù)據(jù)是響應(yīng)式的,但其實(shí)模板中并不是所有的數(shù)據(jù)都是響應(yīng)式的暮胧。有一些數(shù)據(jù)首次渲染后就不會(huì)再變化锐借,對(duì)應(yīng)的DOM也不會(huì)變化问麸。那么優(yōu)化過程就是深度遍歷AST樹,按照相關(guān)條件對(duì)樹節(jié)點(diǎn)進(jìn)行標(biāo)記钞翔。這些被標(biāo)記的節(jié)點(diǎn)(靜態(tài)節(jié)點(diǎn))我們就可以跳過對(duì)它們的比對(duì)严卖,對(duì)運(yùn)行時(shí)的模板起到很大的優(yōu)化作用。

編譯的最后一步是將優(yōu)化后的AST樹轉(zhuǎn)換為可執(zhí)行的代碼布轿。

MVVM的優(yōu)缺點(diǎn)?

優(yōu)點(diǎn):

  • 分離視圖(View)和模型(Model)哮笆,降低代碼耦合,提?視圖或者邏輯的重?性: ?如視圖(View)可以獨(dú)?于Model變化和修改汰扭,?個(gè)ViewModel可以綁定不同的"View"上稠肘,當(dāng)View變化的時(shí)候Model不可以不變,當(dāng)Model變化的時(shí)候View也可以不變萝毛。你可以把?些視圖邏輯放在?個(gè)ViewModel??项阴,讓很多view重?這段視圖邏輯
  • 提?可測(cè)試性: ViewModel的存在可以幫助開發(fā)者更好地編寫測(cè)試代碼
  • ?動(dòng)更新dom: 利?雙向綁定,數(shù)據(jù)更新后視圖?動(dòng)更新,讓開發(fā)者從繁瑣的?動(dòng)dom中解放

缺點(diǎn):

  • Bug很難被調(diào)試: 因?yàn)槭?雙向綁定的模式,當(dāng)你看到界?異常了笆包,有可能是你View的代碼有Bug环揽,也可能是Model的代碼有問題。數(shù)據(jù)綁定使得?個(gè)位置的Bug被快速傳遞到別的位置色查,要定位原始出問題的地?就變得不那么容易了薯演。另外,數(shù)據(jù)綁定的聲明是指令式地寫在View的模版當(dāng)中的秧了,這些內(nèi)容是沒辦法去打斷點(diǎn)debug的
  • ?個(gè)?的模塊中model也會(huì)很?跨扮,雖然使??便了也很容易保證了數(shù)據(jù)的?致性,當(dāng)時(shí)?期持有验毡,不釋放內(nèi)存就造成了花費(fèi)更多的內(nèi)存
  • 對(duì)于?型的圖形應(yīng)?程序衡创,視圖狀態(tài)較多,ViewModel的構(gòu)建和維護(hù)的成本都會(huì)?較?晶通。

Vue data 中某一個(gè)屬性的值發(fā)生改變后璃氢,視圖會(huì)立即同步執(zhí)行重新渲染嗎?

不會(huì)立即同步執(zhí)行重新渲染狮辽。Vue 實(shí)現(xiàn)響應(yīng)式并不是數(shù)據(jù)發(fā)生變化之后 DOM 立即變化一也,而是按一定的策略進(jìn)行 DOM 的更新。Vue 在更新 DOM 時(shí)是異步執(zhí)行的喉脖。只要偵聽到數(shù)據(jù)變化椰苟, Vue 將開啟一個(gè)隊(duì)列,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)變更树叽。

如果同一個(gè)watcher被多次觸發(fā)舆蝴,只會(huì)被推入到隊(duì)列中一次。這種在緩沖時(shí)去除重復(fù)數(shù)據(jù)對(duì)于避免不必要的計(jì)算和 DOM 操作是非常重要的。然后洁仗,在下一個(gè)的事件循環(huán)tick中层皱,Vue 刷新隊(duì)列并執(zhí)行實(shí)際(已去重的)工作。

diff算法

時(shí)間復(fù)雜度: 個(gè)樹的完全 diff 算法是一個(gè)時(shí)間復(fù)雜度為 O(n*3) 赠潦,vue進(jìn)行優(yōu)化轉(zhuǎn)化成 O(n) 叫胖。

理解:

  • 最小量更新, key 很重要她奥。這個(gè)可以是這個(gè)節(jié)點(diǎn)的唯一標(biāo)識(shí)臭家,告訴 diff 算法,在更改前后它們是同一個(gè)DOM節(jié)點(diǎn)

    • 擴(kuò)展 v-for 為什么要有 key 方淤,沒有 key 會(huì)暴力復(fù)用,舉例子的話隨便說(shuō)一個(gè)比如移動(dòng)節(jié)點(diǎn)或者增加節(jié)點(diǎn)(修改DOM)蹄殃,加 key 只會(huì)移動(dòng)減少操作DOM携茂。
  • 只有是同一個(gè)虛擬節(jié)點(diǎn)才會(huì)進(jìn)行精細(xì)化比較,否則就是暴力刪除舊的诅岩,插入新的讳苦。

  • 只進(jìn)行同層比較,不會(huì)進(jìn)行跨層比較吩谦。

diff算法的優(yōu)化策略:四種命中查找鸳谜,四個(gè)指針

  1. 舊前與新前(先比開頭,后插入和刪除節(jié)點(diǎn)的這種情況)
  2. 舊后與新后(比結(jié)尾式廷,前插入或刪除的情況)
  3. 舊前與新后(頭與尾比咐扭,此種發(fā)生了,涉及移動(dòng)節(jié)點(diǎn)滑废,那么新前指向的節(jié)點(diǎn)蝗肪,移動(dòng)到舊后之后)
  4. 舊后與新前(尾與頭比,此種發(fā)生了蠕趁,涉及移動(dòng)節(jié)點(diǎn)薛闪,那么新前指向的節(jié)點(diǎn),移動(dòng)到舊前之前)

--- 問完上面這些如果都能很清楚的話俺陋,基本O了 ---

以下的這些簡(jiǎn)單的概念豁延,你肯定也是沒有問題的啦??

Vue的優(yōu)點(diǎn)

  • 輕量級(jí)框架:只關(guān)注視圖層,是一個(gè)構(gòu)建數(shù)據(jù)的視圖集合腊状,大小只有幾十 kb 诱咏;
  • 簡(jiǎn)單易學(xué):國(guó)人開發(fā),中文文檔寿酌,不存在語(yǔ)言障礙 胰苏,易于理解和學(xué)習(xí);
  • 雙向數(shù)據(jù)綁定:保留了 angular 的特點(diǎn),在數(shù)據(jù)操作方面更為簡(jiǎn)單硕并;
  • 組件化:保留了 react 的優(yōu)點(diǎn)法焰,實(shí)現(xiàn)了 html 的封裝和重用,在構(gòu)建單頁(yè)面應(yīng)用方面有著獨(dú)特的優(yōu)勢(shì)倔毙;
  • 視圖埃仪,數(shù)據(jù),結(jié)構(gòu)分離:使數(shù)據(jù)的更改更為簡(jiǎn)單陕赃,不需要進(jìn)行邏輯代碼的修改卵蛉,只需要操作數(shù)據(jù)就能完成相關(guān)操作;
  • 虛擬DOM:dom 操作是非常耗費(fèi)性能的么库,不再使用原生的 dom 操作節(jié)點(diǎn)傻丝,極大解放 dom 操作,但具體操作的還是 dom 不過是換了另一種方式诉儒;
  • 運(yùn)行速度更快:相比較于 react 而言葡缰,同樣是操作虛擬 dom,就性能而言忱反, vue 存在很大的優(yōu)勢(shì)泛释。

vue-router 路由鉤子函數(shù)是什么 執(zhí)行順序是什么

路由鉤子的執(zhí)行流程, 鉤子函數(shù)種類有:全局守衛(wèi)、路由守衛(wèi)温算、組件守衛(wèi)

完整的導(dǎo)航解析流程:

  1. 導(dǎo)航被觸發(fā)怜校。
  2. 在失活的組件里調(diào)用 beforeRouteLeave 守衛(wèi)。
  3. 調(diào)用全局的 beforeEach 守衛(wèi)注竿。
  4. 在重用的組件里調(diào)用 beforeRouteUpdate 守衛(wèi) (2.2+)茄茁。
  5. 在路由配置里調(diào)用 beforeEnter。
  6. 解析異步路由組件蔓搞。
  7. 在被激活的組件里調(diào)用 beforeRouteEnter胰丁。
  8. 調(diào)用全局的 beforeResolve 守衛(wèi) (2.5+)。
  9. 導(dǎo)航被確認(rèn)喂分。
  10. 調(diào)用全局的 afterEach 鉤子锦庸。
  11. 觸發(fā) DOM 更新。
  12. 調(diào)用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)蒲祈,創(chuàng)建好的組件實(shí)例會(huì)作為回調(diào)函數(shù)的參數(shù)傳入甘萧。

Vue.js的template編譯

簡(jiǎn)而言之,就是先轉(zhuǎn)化成AST樹梆掸,再得到的render函數(shù)返回VNode(Vue的虛擬DOM節(jié)點(diǎn))扬卷,詳細(xì)步驟如下:

首先,通過compile編譯器把template編譯成AST語(yǔ)法樹(abstract syntax tree 即 源代碼的抽象語(yǔ)法結(jié)構(gòu)的樹狀表現(xiàn)形式)酸钦,compile是createCompiler的返回值怪得,createCompiler是用以創(chuàng)建編譯器的。另外compile還負(fù)責(zé)合并option。

然后徒恋,AST會(huì)經(jīng)過generate(將AST語(yǔ)法樹轉(zhuǎn)化成render funtion字符串的過程)得到render函數(shù)蚕断,render的返回值是VNode,VNode是Vue的虛擬DOM節(jié)點(diǎn)入挣,里面有(標(biāo)簽名亿乳、子節(jié)點(diǎn)、文本等等)

$nextTick 是什么径筏?

Vue 實(shí)現(xiàn)響應(yīng)式并不是在數(shù)據(jù)發(fā)生后立即更新 DOM葛假,使用 vm.$nextTick 是在下次 DOM 更新循環(huán)結(jié)束之后立即執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后使用滋恬,則可以在回調(diào)中獲取更新后的 DOM聊训。

說(shuō)說(shuō)Vue的生命周期吧

什么時(shí)候被調(diào)用?

  • beforeCreate :實(shí)例初始化之后恢氯,數(shù)據(jù)觀測(cè)之前調(diào)用
  • created:實(shí)例創(chuàng)建萬(wàn)之后調(diào)用魔眨。實(shí)例完成:數(shù)據(jù)觀測(cè)、屬性和方法的運(yùn)算酿雪、 watch/event 事件回調(diào)。無(wú) $el .
  • beforeMount:在掛載之前調(diào)用侄刽,相關(guān) render 函數(shù)首次被調(diào)用
  • mounted:了被新創(chuàng)建的vm.$el替換指黎,并掛載到實(shí)例上去之后調(diào)用改鉤子。
  • beforeUpdate:數(shù)據(jù)更新前調(diào)用州丹,發(fā)生在虛擬DOM重新渲染和打補(bǔ)丁醋安,在這之后會(huì)調(diào)用改鉤子。
  • updated:由于數(shù)據(jù)更改導(dǎo)致的虛擬DOM重新渲染和打補(bǔ)丁墓毒,在這之后會(huì)調(diào)用改鉤子吓揪。
  • beforeDestroy:實(shí)例銷毀前調(diào)用,實(shí)例仍然可用所计。
  • destroyed:實(shí)例銷毀之后調(diào)用柠辞,調(diào)用后,Vue實(shí)例指示的所有東西都會(huì)解綁主胧,所有事件監(jiān)聽器和所有子實(shí)例都會(huì)被移除

每個(gè)生命周期內(nèi)部可以做什么叭首?

  • created:實(shí)例已經(jīng)創(chuàng)建完成,因?yàn)樗亲钤缬|發(fā)的踪栋,所以可以進(jìn)行一些數(shù)據(jù)焙格、資源的請(qǐng)求。
  • mounted:實(shí)例已經(jīng)掛載完成夷都,可以進(jìn)行一些DOM操作眷唉。
  • beforeUpdate:可以在這個(gè)鉤子中進(jìn)一步的更改狀態(tài),不會(huì)觸發(fā)重渲染。
  • updated:可以執(zhí)行依賴于DOM的操作冬阳,但是要避免更改狀態(tài)蛤虐,可能會(huì)導(dǎo)致更新無(wú)線循環(huán)。
  • destroyed:可以執(zhí)行一些優(yōu)化操作摩泪,清空計(jì)時(shí)器笆焰,解除綁定事件。

ajax放在哪個(gè)生命周期见坑?:一般放在 mounted 中嚷掠,保證邏輯統(tǒng)一性,因?yàn)樯芷谑峭綀?zhí)行的荞驴, ajax 是異步執(zhí)行的不皆。單數(shù)服務(wù)端渲染 ssr 同一放在 created 中,因?yàn)榉?wù)端渲染不支持 mounted 方法熊楼。 什么時(shí)候使用beforeDestroy霹娄?:當(dāng)前頁(yè)面使用 $on ,需要解綁事件鲫骗。清楚定時(shí)器犬耻。解除事件綁定, scroll mousemove 执泰。

Vue 怎么用 vm.$set() 解決對(duì)象新增屬性不能響應(yīng)的問題 枕磁?

受現(xiàn)代 JavaScript 的限制 ,Vue 無(wú)法檢測(cè)到對(duì)象屬性的添加或刪除术吝。由于 Vue 會(huì)在初始化實(shí)例時(shí)對(duì)屬性執(zhí)行 getter/setter 轉(zhuǎn)化计济,所以屬性必須在 data 對(duì)象上存在才能讓 Vue 將它轉(zhuǎn)換為響應(yīng)式的。但是 Vue 提供了 Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value) 來(lái)實(shí)現(xiàn)為對(duì)象添加響應(yīng)式屬性排苍,那框架本身是如何實(shí)現(xiàn)的呢沦寂?

我們查看對(duì)應(yīng)的 Vue 源碼:vue/src/core/instance/index.js

export function set (target: Array<any> | Object, key: any, val: any): any {
  // target 為數(shù)組  
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    // 修改數(shù)組的長(zhǎng)度, 避免索引>數(shù)組長(zhǎng)度導(dǎo)致splcie()執(zhí)行有誤
    target.length = Math.max(target.length, key)
    // 利用數(shù)組的splice變異方法觸發(fā)響應(yīng)式  
    target.splice(key, 1, val)
    return val
  }
  // key 已經(jīng)存在,直接修改屬性值  
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  // target 本身就不是響應(yīng)式數(shù)據(jù), 直接賦值
  if (!ob) {
    target[key] = val
    return val
  }
  // 對(duì)屬性進(jìn)行響應(yīng)式處理
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val
}

我們閱讀以上源碼可知淘衙,vm.$set 的實(shí)現(xiàn)原理是:

  • 如果目標(biāo)是數(shù)組传藏,直接使用數(shù)組的 splice 方法觸發(fā)相應(yīng)式;
  • 如果目標(biāo)是對(duì)象彤守,會(huì)先判讀屬性是否存在漩氨、對(duì)象是否是響應(yīng)式,最終如果要對(duì)屬性進(jìn)行響應(yīng)式處理遗增,則是通過調(diào)用 defineReactive 方法進(jìn)行響應(yīng)式處理( defineReactive 方法就是 Vue 在初始化對(duì)象時(shí)叫惊,給對(duì)象屬性采用 Object.defineProperty 動(dòng)態(tài)添加 getter 和 setter 的功能所調(diào)用的方法)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市做修,隨后出現(xiàn)的幾起案子霍狰,更是在濱河造成了極大的恐慌抡草,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔗坯,死亡現(xiàn)場(chǎng)離奇詭異康震,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)宾濒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門腿短,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人绘梦,你說(shuō)我怎么就攤上這事橘忱。” “怎么了卸奉?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵钝诚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我榄棵,道長(zhǎng)凝颇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任疹鳄,我火速辦了婚禮拧略,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘪弓。我一直安慰自己辑鲤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布杠茬。 她就那樣靜靜地躺著,像睡著了一般弛随。 火紅的嫁衣襯著肌膚如雪瓢喉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天舀透,我揣著相機(jī)與錄音栓票,去河邊找鬼。 笑死愕够,一個(gè)胖子當(dāng)著我的面吹牛走贪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惑芭,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼坠狡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了遂跟?” 一聲冷哼從身側(cè)響起逃沿,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤婴渡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后凯亮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體边臼,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年假消,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了柠并。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡富拗,死狀恐怖臼予,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情媒峡,我是刑警寧澤瘟栖,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站谅阿,受9級(jí)特大地震影響半哟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜签餐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一寓涨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧氯檐,春花似錦戒良、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至河泳,卻和暖如春沃呢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拆挥。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工薄霜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纸兔。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓惰瓜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親汉矿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子崎坊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容