vue高頻面試題合集(四)附答案

vue初始化頁面閃動問題

使用vue開發(fā)時,在vue初始化之前,由于div是不歸vue管的,所以我們寫的代碼在還沒有解析的情況下會容易出現(xiàn)花屏現(xiàn)象,看到類似于{{message}}的字樣,雖然一般情況下這個時間很短暫,但是還是有必要讓解決這個問題的。

首先:在css里加上以下代碼:

[v-cloak] {    display: none;}
復(fù)制代碼

如果沒有徹底解決問題,則在根元素加上style="display: none;" :style="{display: 'block'}"

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

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

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

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

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

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

生命周期鉤子是如何實現(xiàn)的

Vue 的生命周期鉤子核心實現(xiàn)是利用發(fā)布訂閱模式先把用戶傳入的的生命周期鉤子訂閱好(內(nèi)部采用數(shù)組的方式存儲)然后在創(chuàng)建組件實例的過程中會一次執(zhí)行對應(yīng)的鉤子方法(發(fā)布)

相關(guān)代碼如下

export function callHook(vm, hook) {
  // 依次執(zhí)行生命周期對應(yīng)的方法
  const handlers = vm.$options[hook];
  if (handlers) {
    for (let i = 0; i < handlers.length; i++) {
      handlers[i].call(vm); //生命周期里面的this指向當(dāng)前實例
    }
  }
}

// 調(diào)用的時候
Vue.prototype._init = function (options) {
  const vm = this;
  vm.$options = mergeOptions(vm.constructor.options, options);
  callHook(vm, "beforeCreate"); //初始化數(shù)據(jù)之前
  // 初始化狀態(tài)
  initState(vm);
  callHook(vm, "created"); //初始化數(shù)據(jù)之后
  if (vm.$options.el) {
    vm.$mount(vm.$options.el);
  }
};

Vue為什么沒有類似于React中shouldComponentUpdate的生命周期?

考點: Vue的變化偵測原理

前置知識: 依賴收集、虛擬DOM、響應(yīng)式系統(tǒng)

根本原因是Vue與React的變化偵測方式有所不同

React是pull的方式偵測變化,當(dāng)React知道發(fā)生變化后,會使用Virtual Dom Diff進(jìn)行差異檢測,但是很多組件實際上是肯定不會發(fā)生變化的,這個時候需要用shouldComponentUpdate進(jìn)行手動操作來減少diff,從而提高程序整體的性能.

Vue是pull+push的方式偵測變化的,在一開始就知道那個組件發(fā)生了變化,因此在push的階段并不需要手動控制diff,而組件內(nèi)部采用的diff方式實際上是可以引入類似于shouldComponentUpdate相關(guān)生命周期的,但是通常合理大小的組件不會有過量的diff,手動優(yōu)化的價值有限,因此目前Vue并沒有考慮引入shouldComponentUpdate這種手動優(yōu)化的生命周期.

了解nextTick嗎?

異步方法,異步渲染最后一步,與JS事件循環(huán)聯(lián)系緊密。主要使用了宏任務(wù)微任務(wù)(setTimeout、promise那些),定義了一個異步方法,多次調(diào)用nextTick會將方法存入隊列,通過異步方法清空當(dāng)前隊列。

Vue 組件通訊有哪幾種方式

  1. props 和emit 父組件向子組件傳遞數(shù)據(jù)是通過 prop 傳遞的,子組件傳遞數(shù)據(jù)給父組件是通過emit 觸發(fā)事件來做到的
  2. parent,children 獲取當(dāng)前組件的父組件和當(dāng)前組件的子組件
  3. attrs 和listeners A->B->C。Vue 2.4 開始提供了attrs 和listeners 來解決這個問題
  4. 父組件中通過 provide 來提供變量,然后在子組件中通過 inject 來注入變量。(官方不推薦在實際業(yè)務(wù)中使用,但是寫組件庫時很常用)
  5. $refs 獲取組件實例
  6. envetBus 兄弟組件數(shù)據(jù)傳遞 這種情況下可以使用事件總線的方式
  7. vuex 狀態(tài)管理

談一下對 vuex 的個人理解

vuex 是專門為 vue 提供的全局狀態(tài)管理系統(tǒng),用于多個組件中數(shù)據(jù)共享、數(shù)據(jù)緩存等。(無法持久化、內(nèi)部核心原理是通過創(chuàng)造一個全局實例 new Vue)

主要包括以下幾個模塊:

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

了解nextTick嗎?

異步方法,異步渲染最后一步,與JS事件循環(huán)聯(lián)系緊密。主要使用了宏任務(wù)微任務(wù)(setTimeout、promise那些),定義了一個異步方法,多次調(diào)用nextTick會將方法存入隊列,通過異步方法清空當(dāng)前隊列。

說一下Vue的生命周期

Vue 實例有?個完整的?命周期,也就是從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模版、掛載Dom -> 渲染、更新 -> 渲染、卸載 等?系列過程,稱這是Vue的?命周期。

  1. beforeCreate(創(chuàng)建前):數(shù)據(jù)觀測和初始化事件還未開始,此時 data 的響應(yīng)式追蹤、event/watcher 都還沒有被設(shè)置,也就是說不能訪問到data、computed、watch、methods上的方法和數(shù)據(jù)。
  2. created(創(chuàng)建后) :實例創(chuàng)建完成,實例上配置的 options 包括 data、computed、watch、methods 等都配置完成,但是此時渲染得節(jié)點還未掛載到 DOM,所以不能訪問到 $el 屬性。
  3. beforeMount(掛載前):在掛載開始之前被調(diào)用,相關(guān)的render函數(shù)首次被調(diào)用。實例已完成以下的配置:編譯模板,把data里面的數(shù)據(jù)和模板生成html。此時還沒有掛載html到頁面上。
  4. mounted(掛載后):在el被新創(chuàng)建的 vm.$el 替換,并掛載到實例上去之后調(diào)用。實例已完成以下的配置:用上面編譯好的html內(nèi)容替換el屬性指向的DOM對象。完成模板中的html渲染到html 頁面中。此過程中進(jìn)行ajax交互。
  5. beforeUpdate(更新前):響應(yīng)式數(shù)據(jù)更新時調(diào)用,此時雖然響應(yīng)式數(shù)據(jù)更新了,但是對應(yīng)的真實 DOM 還沒有被渲染。
  6. updated(更新后) :在由于數(shù)據(jù)更改導(dǎo)致的虛擬DOM重新渲染和打補丁之后調(diào)用。此時 DOM 已經(jīng)根據(jù)響應(yīng)式數(shù)據(jù)的變化更新了。調(diào)用時,組件 DOM已經(jīng)更新,所以可以執(zhí)行依賴于DOM的操作。然而在大多數(shù)情況下,應(yīng)該避免在此期間更改狀態(tài),因為這可能會導(dǎo)致更新無限循環(huán)。該鉤子在服務(wù)器端渲染期間不被調(diào)用。
  7. beforeDestroy(銷毀前):實例銷毀之前調(diào)用。這一步,實例仍然完全可用,this 仍能獲取到實例。
  8. destroyed(銷毀后):實例銷毀后調(diào)用,調(diào)用后,Vue 實例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除,所有的子實例也會被銷毀。該鉤子在服務(wù)端渲染期間不被調(diào)用。

另外還有 keep-alive 獨有的生命周期,分別為 activateddeactivated 。用 keep-alive 包裹的組件在切換時不會進(jìn)行銷毀,而是緩存到內(nèi)存中并執(zhí)行 deactivated 鉤子函數(shù),命中緩存渲染后會執(zhí)行 activated 鉤子函數(shù)。

Vuex的嚴(yán)格模式是什么,有什么作用,如何開啟?

在嚴(yán)格模式下,無論何時發(fā)生了狀態(tài)變更且不是由mutation函數(shù)引起的,將會拋出錯誤。這能保證所有的狀態(tài)變更都能被調(diào)試工具跟蹤到。

在Vuex.Store 構(gòu)造器選項中開啟,如下

const store = new Vuex.Store({
    strict:true,
})
復(fù)制代碼

Redux 和 Vuex 有什么區(qū)別,它們的共同思想

(1)Redux 和 Vuex區(qū)別

  • Vuex改進(jìn)了Redux中的Action和Reducer函數(shù),以mutations變化函數(shù)取代Reducer,無需switch,只需在對應(yīng)的mutation函數(shù)里改變state值即可
  • Vuex由于Vue自動重新渲染的特性,無需訂閱重新渲染函數(shù),只要生成新的State即可
  • Vuex數(shù)據(jù)流的順序是∶View調(diào)用store.commit提交對應(yīng)的請求到Store中對應(yīng)的mutation函數(shù)->store改變(vue檢測到數(shù)據(jù)變化自動渲染)

通俗點理解就是,vuex 弱化 dispatch,通過commit進(jìn)行 store狀態(tài)的一次更變;取消了action概念,不必傳入特定的 action形式進(jìn)行指定變更;弱化reducer,基于commit參數(shù)直接對數(shù)據(jù)進(jìn)行轉(zhuǎn)變,使得框架更加簡易;

(2)共同思想

  • 單—的數(shù)據(jù)源
  • 變化可以預(yù)測

本質(zhì)上:redux與vuex都是對mvvm思想的服務(wù),將數(shù)據(jù)從視圖中抽離的一種方案;
形式上:vuex借鑒了redux,將store作為全局的數(shù)據(jù)中心,進(jìn)行mode管理;

DIFF算法的原理

在新老虛擬DOM對比時:

  • 首先,對比節(jié)點本身,判斷是否為同一節(jié)點,如果不為相同節(jié)點,則刪除該節(jié)點重新創(chuàng)建節(jié)點進(jìn)行替換
  • 如果為相同節(jié)點,進(jìn)行patchVnode,判斷如何對該節(jié)點的子節(jié)點進(jìn)行處理,先判斷一方有子節(jié)點一方?jīng)]有子節(jié)點的情況(如果新的children沒有子節(jié)點,將舊的子節(jié)點移除)
  • 比較如果都有子節(jié)點,則進(jìn)行updateChildren,判斷如何對這些新老節(jié)點的子節(jié)點進(jìn)行操作(diff核心)。
  • 匹配時,找到相同的子節(jié)點,遞歸比較子節(jié)點

在diff中,只對同層的子節(jié)點進(jìn)行比較,放棄跨級的節(jié)點比較,使得時間復(fù)雜從O(n3)降低值O(n),也就是說,只有當(dāng)新舊children都為多個子節(jié)點時才需要用核心的Diff算法進(jìn)行同層級比較。

nextTick 使用場景和原理

nextTick 中的回調(diào)是在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行的延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個方法,獲取更新后的 DOM。主要思路就是采用微任務(wù)優(yōu)先的方式調(diào)用異步方法去執(zhí)行 nextTick 包裝的方法

相關(guān)代碼如下

let callbacks = [];
let pending = false;
function flushCallbacks() {
  pending = false; //把標(biāo)志還原為false
  // 依次執(zhí)行回調(diào)
  for (let i = 0; i < callbacks.length; i++) {
    callbacks[i]();
  }
}
let timerFunc; //定義異步方法  采用優(yōu)雅降級
if (typeof Promise !== "undefined") {
  // 如果支持promise
  const p = Promise.resolve();
  timerFunc = () => {
    p.then(flushCallbacks);
  };
} else if (typeof MutationObserver !== "undefined") {
  // MutationObserver 主要是監(jiān)聽dom變化 也是一個異步方法
  let counter = 1;
  const observer = new MutationObserver(flushCallbacks);
  const textNode = document.createTextNode(String(counter));
  observer.observe(textNode, {
    characterData: true,
  });
  timerFunc = () => {
    counter = (counter + 1) % 2;
    textNode.data = String(counter);
  };
} else if (typeof setImmediate !== "undefined") {
  // 如果前面都不支持 判斷setImmediate
  timerFunc = () => {
    setImmediate(flushCallbacks);
  };
} else {
  // 最后降級采用setTimeout
  timerFunc = () => {
    setTimeout(flushCallbacks, 0);
  };
}

export function nextTick(cb) {
  // 除了渲染watcher  還有用戶自己手動調(diào)用的nextTick 一起被收集到數(shù)組
  callbacks.push(cb);
  if (!pending) {
    // 如果多次調(diào)用nextTick  只會執(zhí)行一次異步 等異步隊列清空之后再把標(biāo)志變?yōu)閒alse
    pending = true;
    timerFunc();
  }
}

對keep-alive的理解,它是如何實現(xiàn)的,具體緩存的是什么?

如果需要在組件切換的時候,保存一些組件的狀態(tài)防止多次渲染,就可以使用 keep-alive 組件包裹需要保存的組件。

(1)keep-alive

keep-alive有以下三個屬性:

  • include 字符串或正則表達(dá)式,只有名稱匹配的組件會被匹配;
  • exclude 字符串或正則表達(dá)式,任何名稱匹配的組件都不會被緩存;
  • max 數(shù)字,最多可以緩存多少組件實例。

注意:keep-alive 包裹動態(tài)組件時,會緩存不活動的組件實例。

主要流程

  1. 判斷組件 name ,不在 include 或者在 exclude 中,直接返回 vnode,說明該組件不被緩存。
  2. 獲取組件實例 key ,如果有獲取實例的 key,否則重新生成。
  3. key生成規(guī)則,cid +"∶∶"+ tag ,僅靠cid是不夠的,因為相同的構(gòu)造函數(shù)可以注冊為不同的本地組件。
  4. 如果緩存對象內(nèi)存在,則直接從緩存對象中獲取組件實例給 vnode ,不存在則添加到緩存對象中。 5.最大緩存數(shù)量,當(dāng)緩存組件數(shù)量超過 max 值時,清除 keys 數(shù)組內(nèi)第一個組件。

(2)keep-alive 的實現(xiàn)

const patternTypes: Array<Function> = [String, RegExp, Array] // 接收:字符串,正則,數(shù)組

export default {
  name: 'keep-alive',
  abstract: true, // 抽象組件,是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出現(xiàn)在父組件鏈中。

  props: {
    include: patternTypes, // 匹配的組件,緩存
    exclude: patternTypes, // 不去匹配的組件,不緩存
    max: [String, Number], // 緩存組件的最大實例數(shù)量, 由于緩存的是組件實例(vnode),數(shù)量過多的時候,會占用過多的內(nèi)存,可以用max指定上限
  },

  created() {
    // 用于初始化緩存虛擬DOM數(shù)組和vnode的key
    this.cache = Object.create(null)
    this.keys = []
  },

  destroyed() {
    // 銷毀緩存cache的組件實例
    for (const key in this.cache) {
      pruneCacheEntry(this.cache, key, this.keys)
    }
  },

  mounted() {
    // prune 削減精簡[v.]
    // 去監(jiān)控include和exclude的改變,根據(jù)最新的include和exclude的內(nèi)容,來實時削減緩存的組件的內(nèi)容
    this.$watch('include', (val) => {
      pruneCache(this, (name) => matches(val, name))
    })
    this.$watch('exclude', (val) => {
      pruneCache(this, (name) => !matches(val, name))
    })
  },
}
復(fù)制代碼

render函數(shù):

  1. 會在 keep-alive 組件內(nèi)部去寫自己的內(nèi)容,所以可以去獲取默認(rèn) slot 的內(nèi)容,然后根據(jù)這個去獲取組件
  2. keep-alive 只對第一個組件有效,所以獲取第一個子組件。
  3. 和 keep-alive 搭配使用的一般有:動態(tài)組件 和router-view
render () {
  //
  function getFirstComponentChild (children: ?Array<VNode>): ?VNode {
    if (Array.isArray(children)) {
  for (let i = 0; i < children.length; i++) {
    const c = children[i]
    if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
      return c
    }
  }
  }
  }
  const slot = this.$slots.default // 獲取默認(rèn)插槽
  const vnode: VNode = getFirstComponentChild(slot)// 獲取第一個子組件
  const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions // 組件參數(shù)
  if (componentOptions) { // 是否有組件參數(shù)
    // check pattern
    const name: ?string = getComponentName(componentOptions) // 獲取組件名
    const { include, exclude } = this
    if (
      // not included
      (include && (!name || !matches(include, name))) ||
      // excluded
      (exclude && name && matches(exclude, name))
    ) {
      // 如果不匹配當(dāng)前組件的名字和include以及exclude
      // 那么直接返回組件的實例
      return vnode
    }

    const { cache, keys } = this

    // 獲取這個組件的key
    const key: ?string = vnode.key == null
      // same constructor may get registered as different local components
      // so cid alone is not enough (#3269)
      ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
      : vnode.key

    if (cache[key]) {
      // LRU緩存策略執(zhí)行
      vnode.componentInstance = cache[key].componentInstance // 組件初次渲染的時候componentInstance為undefined

      // make current key freshest
      remove(keys, key)
      keys.push(key)
      // 根據(jù)LRU緩存策略執(zhí)行,將key從原來的位置移除,然后將這個key值放到最后面
    } else {
      // 在緩存列表里面沒有的話,則加入,同時判斷當(dāng)前加入之后,是否超過了max所設(shè)定的范圍,如果是,則去除
      // 使用時間間隔最長的一個
      cache[key] = vnode
      keys.push(key)
      // prune oldest entry
      if (this.max && keys.length > parseInt(this.max)) {
        pruneCacheEntry(cache, keys[0], keys, this._vnode)
      }
    }
    // 將組件的keepAlive屬性設(shè)置為true
    vnode.data.keepAlive = true // 作用:判斷是否要執(zhí)行組件的created、mounted生命周期函數(shù)
  }
  return vnode || (slot && slot[0])
}
復(fù)制代碼

keep-alive 具體是通過 cache 數(shù)組緩存所有組件的 vnode 實例。當(dāng) cache 內(nèi)原有組件被使用時會將該組件 key 從 keys 數(shù)組中刪除,然后 push 到 keys數(shù)組最后,以便清除最不常用組件。

實現(xiàn)步驟:

  1. 獲取 keep-alive 下第一個子組件的實例對象,通過他去獲取這個組件的組件名

  2. 通過當(dāng)前組件名去匹配原來 include 和 exclude,判斷當(dāng)前組件是否需要緩存,不需要緩存,直接返回當(dāng)前組件的實例vNode

  3. 需要緩存,判斷他當(dāng)前是否在緩存數(shù)組里面:

  • 存在,則將他原來位置上的 key 給移除,同時將這個組件的 key 放到數(shù)組最后面(LRU)

  • 不存在,將組件 key 放入數(shù)組,然后判斷當(dāng)前 key數(shù)組是否超過 max 所設(shè)置的范圍,超過,那么削減未使用時間最長的一個組件的 key

  1. 最后將這個組件的 keepAlive 設(shè)置為 true

(3)keep-alive 本身的創(chuàng)建過程和 patch 過程

緩存渲染的時候,會根據(jù) vnode.componentInstance(首次渲染 vnode.componentInstance 為 undefined) 和 keepAlive 屬性判斷不會執(zhí)行組件的 created、mounted 等鉤子函數(shù),而是對緩存的組件執(zhí)行 patch 過程∶ 直接把緩存的 DOM 對象直接插入到目標(biāo)元素中,完成了數(shù)據(jù)更新的情況下的渲染過程。

首次渲染

  • 組件的首次渲染∶判斷組件的 abstract 屬性,才往父組件里面掛載 DOM
// core/instance/lifecycle
function initLifecycle (vm: Component) {
  const options = vm.$options

  // locate first non-abstract parent
  let parent = options.parent
  if (parent && !options.abstract) { // 判斷組件的abstract屬性,才往父組件里面掛載DOM
    while (parent.$options.abstract && parent.$parent) {
      parent = parent.$parent
    }
    parent.$children.push(vm)
  }

  vm.$parent = parent
  vm.$root = parent ? parent.$root : vm

  vm.$children = []
  vm.$refs = {}

  vm._watcher = null
  vm._inactive = null
  vm._directInactive = false
  vm._isMounted = false
  vm._isDestroyed = false
  vm._isBeingDestroyed = false
}
復(fù)制代碼
  • 判斷當(dāng)前 keepAlive 和 componentInstance 是否存在來判斷是否要執(zhí)行組件 prepatch 還是執(zhí)行創(chuàng)建 componentlnstance
// core/vdom/create-component
init (vnode: VNodeWithData, hydrating: boolean): ?boolean {
    if (
      vnode.componentInstance &&
      !vnode.componentInstance._isDestroyed &&
      vnode.data.keepAlive
    ) { // componentInstance在初次是undefined!!!
      // kept-alive components, treat as a patch
      const mountedNode: any = vnode // work around flow
      componentVNodeHooks.prepatch(mountedNode, mountedNode) // prepatch函數(shù)執(zhí)行的是組件更新的過程
    } else {
      const child = vnode.componentInstance = createComponentInstanceForVnode(
        vnode,
        activeInstance
      )
      child.$mount(hydrating ? vnode.elm : undefined, hydrating)
    }
  },
復(fù)制代碼

prepatch 操作就不會在執(zhí)行組件的 mounted 和 created 生命周期函數(shù),而是直接將 DOM 插入

(4)LRU (least recently used)緩存策略

LRU 緩存策略∶ 從內(nèi)存中找出最久未使用的數(shù)據(jù)并置換新的數(shù)據(jù)。
LRU(Least rencently used)算法根據(jù)數(shù)據(jù)的歷史訪問記錄來進(jìn)行淘汰數(shù)據(jù),其核心思想是 "如果數(shù)據(jù)最近被訪問過,那么將來被訪問的幾率也更高"。 最常見的實現(xiàn)是使用一個鏈表保存緩存數(shù)據(jù),詳細(xì)算法實現(xiàn)如下∶

  • 新數(shù)據(jù)插入到鏈表頭部
  • 每當(dāng)緩存命中(即緩存數(shù)據(jù)被訪問),則將數(shù)據(jù)移到鏈表頭部
  • 鏈表滿的時候,將鏈表尾部的數(shù)據(jù)丟棄。

computed 的實現(xiàn)原理

computed 本質(zhì)是一個惰性求值的觀察者。

computed 內(nèi)部實現(xiàn)了一個惰性的 watcher,也就是 computed watcher,computed watcher 不會立刻求值,同時持有一個 dep 實例。

其內(nèi)部通過 this.dirty 屬性標(biāo)記計算屬性是否需要重新求值。

當(dāng) computed 的依賴狀態(tài)發(fā)生改變時,就會通知這個惰性的 watcher,

computed watcher 通過 this.dep.subs.length 判斷有沒有訂閱者,

有的話,會重新計算,然后對比新舊值,如果變化了,會重新渲染。 (Vue 想確保不僅僅是計算屬性依賴的值發(fā)生變化,而是當(dāng)計算屬性最終計算的值發(fā)生變化時才會觸發(fā)渲染 watcher 重新渲染,本質(zhì)上是一種優(yōu)化。)

沒有的話,僅僅把 this.dirty = true。 (當(dāng)計算屬性依賴于其他數(shù)據(jù)時,屬性并不會立即重新計算,只有之后其他地方需要讀取屬性的時候,它才會真正計算,即具備 lazy(懶計算)特性。)

keep-alive 使用場景和原理

keep-alive 是 Vue 內(nèi)置的一個組件,可以實現(xiàn)組件緩存,當(dāng)組件切換時不會對當(dāng)前組件進(jìn)行卸載。

  • 常用的兩個屬性 include/exclude,允許組件有條件的進(jìn)行緩存。
  • 兩個生命周期 activated/deactivated,用來得知當(dāng)前組件是否處于活躍狀態(tài)。
  • keep-alive 的中還運用了 LRU(最近最少使用) 算法,選擇最近最久未使用的組件予以淘汰。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容