Vue相關(guān)面試題總結(jié)

created跟mounted生命周期方法有什么區(qū)別

  1. created的時(shí)候dom未進(jìn)行渲染,不能做dom相關(guān)的操作
  2. mounted的時(shí)候dom已經(jīng)渲染完成了

vue的 nextTick是如何實(shí)現(xiàn)的

1、執(zhí)行時(shí)機(jī)會(huì)在dom更新完成之后調(diào)用

2、先把所有的回調(diào)任務(wù)都加到callbacks數(shù)組中,然后定義一個(gè)flushCallbacks方法遍歷數(shù)組執(zhí)行回調(diào)函數(shù),最后判斷瀏覽器支持Promise -> new MutationObserver(flushCallbacks) -> setImmediate -> setTimeout 找出一個(gè)方法來執(zhí)行flushCallbacks函數(shù),

3、MutationObserver是一個(gè)監(jiān)聽到DOM更新后,調(diào)用回調(diào)函數(shù)的API,主要目的是在當(dāng)前同步代碼執(zhí)行完畢之后,執(zhí)行我們傳入的回調(diào)函數(shù)

父子組件掛載生命周期順序

先執(zhí)行最內(nèi)層的生命周期,后執(zhí)行最外面的生命周期

vue2中數(shù)組和對(duì)象 數(shù)據(jù)觀察時(shí)有什么特殊處理

對(duì)象是遞歸遍歷每一個(gè)key加數(shù)據(jù)劫持, 數(shù)組是通過重寫其中會(huì)改變?cè)瓟?shù)組內(nèi)容的一些函數(shù),例如push pop splice等等操作函數(shù)

vue2和3中數(shù)據(jù)觀察的區(qū)別

  1. vue2用的是Object.defineProperty定義每一個(gè)key的get以及set方法,在get中收集依賴
  2. 在set中通知Watcher更新
  3. vue3則是通過系統(tǒng)自帶的Proxy做一個(gè)攔截,實(shí)現(xiàn)同樣的效果,也是定義get跟set方法
const dinner = ["test1", "test2"];

const handler = {
  get(target, prop, receiver) {
    //   track(target, prop)
    return Reflect.get(...arguments);
  },
  set(target, key, value, receiver) {
    // trigger(target, key)
    return Reflect.set(...arguments);
  },
};

const proxy = new Proxy(dinner, handler);
console.log(proxy[0]);
proxy[1] = "test3";
console.log(proxy[1]);

vue兄弟節(jié)點(diǎn)通信

  • eventbus
產(chǎn)生事件:
this.$root.$emit('change-color')

接受事件:
this.$root.$on('change-color', () => {
    this.colored = !this.colored
})
import Vue from 'vue'
export default new Vue()   
import bus from './eventBus'; //這里bus != this.$root,但是都可以用來傳遞事件兩者事件不通

虛擬dom解決了什么問題

  1. 首先是正常的一個(gè)真實(shí)dom擁有的屬性非常多,還擁有很多dom操作的方法
  2. 其次數(shù)據(jù)更新的時(shí)候如果整個(gè)畫面重新渲染會(huì)帶來很大的性能開銷,非常慢,而且很多沒變化的部分都屬于無用功,還不能保存數(shù)據(jù)更新前的狀態(tài)
  3. 用新數(shù)據(jù)生成的虛擬dom跟上次舊的虛擬dom做對(duì)比,只更新發(fā)生變化的部分
  4. diff算法也是消耗性能的,所以如果我們知道要修改那個(gè)dom,直接手動(dòng)操作應(yīng)該是最快的,這樣做是為了讓我們更關(guān)注數(shù)據(jù)的變化,而不需要關(guān)心dom操作

vue的diff和react的diff

  • 相同點(diǎn):

都不做跨層比較,只做同層比較,如果某一節(jié)點(diǎn)不同就會(huì)銷毀當(dāng)前的,創(chuàng)建一個(gè)新的

  • 不同點(diǎn):
  1. Vue進(jìn)行diff算法的時(shí)候一邊比較,一邊用新的虛擬dom去更新真實(shí)dom

  2. Vue認(rèn)定相同節(jié)點(diǎn),判斷key、標(biāo)簽、data都要相同
    3.Vue對(duì)比是從兩端到中間做對(duì)比,兩兩進(jìn)行比較,每次對(duì)比完指針往中間移動(dòng)

  3. React是從左往右進(jìn)行對(duì)比,如果同樣把集合最后一個(gè)節(jié)點(diǎn)移動(dòng)到第一個(gè),react會(huì)把前面節(jié)點(diǎn)依次后移,vue會(huì)把最后一個(gè)節(jié)點(diǎn)放在最前面
    通過key值查找新舊節(jié)點(diǎn)中相同可以復(fù)用的節(jié)點(diǎn),因此當(dāng)同類型節(jié)點(diǎn)內(nèi)容不同但是key前后之后可能導(dǎo)致更新失敗的問題

  1. 對(duì)于同樣的abcd -> dabc ,vue會(huì)直接把d拿到第一個(gè), react會(huì)把a(bǔ),b,c摞到最后一個(gè),d不動(dòng);(拿節(jié)點(diǎn)舊Index與當(dāng)前處理到的index進(jìn)行對(duì)比,小于的進(jìn)行移動(dòng),大于index不操作)

兩篇參考文章:

React中diff算法

談?wù)凴eact中Diff算法的策略及實(shí)現(xiàn)

Vue跟react對(duì)比

兩者的模板渲染、兩者的虛擬 dom、diff 差異(vue2、vue3、react 16)、react fiber 能解決什么問題、vue2 的響應(yīng)式原理和 vue3 的響應(yīng)式原理;vue 關(guān)于 Proxy 與 Object.defineProperty 的區(qū)別;兩者的批量更新,還有路由差異、常用的優(yōu)化手段、怎么進(jìn)行數(shù)據(jù)通信、講點(diǎn)新鮮的內(nèi)容:新發(fā)布的 vue3 有什么特性、最后總結(jié),談?wù)剝烧叩娜缃竦纳鷳B(tài)

computed怎么實(shí)現(xiàn)的

computed引入其他computed的屬性是怎么實(shí)現(xiàn)的

watch怎么實(shí)現(xiàn)的

  1. 初始化了一個(gè)Watcher,讀取了一遍數(shù)據(jù),這個(gè)時(shí)候觀察者就會(huì)記錄自己依賴了哪些變量,變化的時(shí)候回調(diào)用回調(diào)函數(shù)
  2. 假如傳入deep,表示深度觀察,get的時(shí)候如果deep是true,就會(huì)讀一遍所有的屬性,調(diào)用get方法的時(shí)候就會(huì)將Watcher添加到每一個(gè)變量的dep中去
Vue.prototype.$watch = function (expOrFn,cb,options) {
    const vm: Component = this
    if (isPlainObject(cb)) {
      return createWatcher(vm, expOrFn, cb, options)
    }
    options = options || {}
    options.user = true
    const watcher = new Watcher(vm, expOrFn, cb, options)
    if (options.immediate) {
      cb.call(vm, watcher.value)
    }
    return function unwatchFn () {
      watcher.teardown()
    }
  }

$on$emit原理

用vm._events[event] = [fn1,fn2],然后$emit去查找vm._events
有沒有這個(gè)事件,有就遍歷調(diào)用同時(shí)綁定this

handler.apply(context, args)

$off: vm._events[event] = null

$once: 調(diào)用完一次就調(diào)用$off關(guān)閉事件

Vue.directive自定義指令

1、用法
//定義
Vue.directive('color', {
  //  el 被綁定元素的元素
  // obj 傳遞的參數(shù)
  bind: function (el, obj) {
    // el.style.color = 'blue'
    el.style.color = obj.value
  }
})
//使用
<div v-color="'red'">11111111111</div>
  1. 作用,比如可以用來自動(dòng)聚焦,定義按鈕防連點(diǎn)等
  2. 存儲(chǔ)如下:
this.options.directives ={ 
color: {bind: ?}
}
{
    'v-focus':{
        name : 'focus' ,  // 指令的名稱
        value : '',       // 指令的值
        arg:'',           // 指令的參數(shù)
        modifiers:{},     // 指令的修飾符
        def:{
            inserted:fn
        }
    }
}

keep-alive

  • 用法:
  1. <keep-alive>組件可接收三個(gè)屬性:
  2. include - 字符串或正則表達(dá)式。只有名稱匹配的組件會(huì)被緩存。
  3. exclude - 字符串或正則表達(dá)式。任何名稱匹配的組件都不會(huì)被緩存。
  4. max - 數(shù)字。最多可以緩存多少組件實(shí)例。
  • 原理:實(shí)際上是把滿足規(guī)則的組件緩存下來
  1. 如果命中緩存就在移除之后放到最后一個(gè)
  2. 如果沒有命中緩存就將當(dāng)前vnode緩存下來
  3. 如果超過max就把第一個(gè)移除
  • 為什么要?jiǎng)h除第一個(gè)緩存組件并且為什么命中緩存了還要調(diào)整組件key的順序?

LRU策略,最近最少使用,把最常用的放在最后,超過限制移除第一個(gè)

this.cache = Object.create(null)
this.cache = {
    'key1':'組件1',
    'key2':'組件2',
    // ...
}
  • 經(jīng)驗(yàn)總結(jié):
  1. keep-alive包裹的組件只會(huì)執(zhí)行一次created、mounted,再次激活就是調(diào)用activated

  2. 總結(jié)用起來很麻煩,有很多緩存不刷新的坑,還不如用強(qiáng)緩存

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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