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

$nextTick 是什么饭耳?

Vue 實現響應式并不是在數據發(fā)生后立即更新 DOM串述,使用 vm.$nextTick 是在下次 DOM 更新循環(huán)結束之后立即執(zhí)行延遲回調。在修改數據之后使用寞肖,則可以在回調中獲取更新后的 DOM纲酗。

一般在哪個生命周期請求異步數據

我們可以在鉤子函數 created、beforeMount新蟆、mounted 中進行調用觅赊,因為在這三個鉤子函數中,data 已經創(chuàng)建琼稻,可以將服務端端返回的數據進行賦值吮螺。

推薦在 created 鉤子函數中調用異步請求,因為在 created 鉤子函數中調用異步請求有以下優(yōu)點:

  • 能更快獲取到服務端數據,減少頁面加載時間鸠补,用戶體驗更好萝风;
  • SSR不支持 beforeMount 、mounted 鉤子函數紫岩,放在 created 中有助于一致性闹丐。

寫過自定義指令嗎 原理是什么

指令本質上是裝飾器,是 vue 對 HTML 元素的擴展被因,給 HTML 元素增加自定義功能。vue 編譯 DOM 時衫仑,會找到指令對象梨与,執(zhí)行指令的相關方法。

自定義指令有五個生命周期(也叫鉤子函數)文狱,分別是 bind粥鞋、inserted、update瞄崇、componentUpdated呻粹、unbind

1. bind:只調用一次,指令第一次綁定到元素時調用苏研。在這里可以進行一次性的初始化設置等浊。

2. inserted:被綁定元素插入父節(jié)點時調用 (僅保證父節(jié)點存在,但不一定已被插入文檔中)摹蘑。

3. update:被綁定于元素所在的模板更新時調用筹燕,而無論綁定值是否變化。通過比較更新前后的綁定值衅鹿,可以忽略不必要的模板更新撒踪。

4. componentUpdated:被綁定元素所在模板完成一次更新周期時調用。

5. unbind:只調用一次大渤,指令與元素解綁時調用制妄。

那vue中是如何檢測數組變化的呢?

數組就是使用object.defineProperty 重新定義數組的每一項泵三,那能引起數組變化的方法我們都是知道的耕捞,poppush 切黔、shift 砸脊、unshiftsplice 纬霞、sort 凌埂、reverse 這七種,只要這些方法執(zhí)行改了數組內容诗芜,我就更新內容就好了瞳抓,是不是很好理解埃疫。

  1. 是用來函數劫持的方式,重寫了數組方法孩哑,具體呢就是更改了數組的原型栓霜,更改成自己的,用戶調數組的一些方法的時候横蜒,走的就是自己的方法胳蛮,然后通知視圖去更新。
  2. 數組里每一項可能是對象丛晌,那么我就是會對數組的每一項進行觀測仅炊,(且只有數組里的對象才能進行觀測,觀測過的也不會進行觀測)

vue3:改用proxy 澎蛛,可直接監(jiān)聽對象數組的變化抚垄。

Vue.js的template編譯

簡而言之,就是先轉化成AST樹谋逻,再得到的render函數返回VNode(Vue的虛擬DOM節(jié)點)呆馁,詳細步驟如下:

首先,通過compile編譯器把template編譯成AST語法樹(abstract syntax tree 即 源代碼的抽象語法結構的樹狀表現形式)毁兆,compile是createCompiler的返回值浙滤,createCompiler是用以創(chuàng)建編譯器的。另外compile還負責合并option气堕。

然后瓷叫,AST會經過generate(將AST語法樹轉化成render funtion字符串的過程)得到render函數,render的返回值是VNode送巡,VNode是Vue的虛擬DOM節(jié)點摹菠,里面有(標簽名、子節(jié)點骗爆、文本等等)

了解nextTick嗎次氨?

異步方法,異步渲染最后一步摘投,與JS事件循環(huán)聯系緊密煮寡。主要使用了宏任務微任務(setTimeoutpromise那些)犀呼,定義了一個異步方法幸撕,多次調用nextTick會將方法存入隊列,通過異步方法清空當前隊列外臂。

nextTick 使用場景和原理

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

相關代碼如下

let callbacks = [];
let pending = false;
function flushCallbacks() {
  pending = false; //把標志還原為false
  // 依次執(zhí)行回調
  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  還有用戶自己手動調用的nextTick 一起被收集到數組
  callbacks.push(cb);
  if (!pending) {
    // 如果多次調用nextTick  只會執(zhí)行一次異步 等異步隊列清空之后再把標志變?yōu)閒alse
    pending = true;
    timerFunc();
  }
}

了解nextTick嗎貌矿?

異步方法炭菌,異步渲染最后一步,與JS事件循環(huán)聯系緊密逛漫。主要使用了宏任務微任務(setTimeout黑低、promise那些),定義了一個異步方法酌毡,多次調用nextTick會將方法存入隊列克握,通過異步方法清空當前隊列。

vue 中使用了哪些設計模式

1.工廠模式 - 傳入參數即可創(chuàng)建實例

虛擬 DOM 根據參數的不同返回基礎標簽的 Vnode 和組件 Vnode

2.單例模式 - 整個程序有且僅有一個實例

vuex 和 vue-router 的插件注冊方法 install 判斷如果系統存在實例就直接返回掉

3.發(fā)布-訂閱模式 (vue 事件機制)

4.觀察者模式 (響應式數據原理)

5.裝飾模式: (@裝飾器的用法)

6.策略模式 策略模式指對象有某個行為,但是在不同的場景中,該行為有不同的實現方案-比如選項的合并策略

Vue 修飾符有哪些

事件修飾符

  • .stop 阻止事件繼續(xù)傳播
  • .prevent 阻止標簽默認行為
  • .capture 使用事件捕獲模式,即元素自身觸發(fā)的事件先在此處處理枷踏,然后才交由內部元素進行處理
  • .self 只當在 event.target 是當前元素自身時觸發(fā)處理函數
  • .once 事件將只會觸發(fā)一次
  • .passive 告訴瀏覽器你不想阻止事件的默認行為

v-model 的修飾符

  • .lazy 通過這個修飾符玛荞,轉變?yōu)樵?change 事件再同步
  • .number 自動將用戶的輸入值轉化為數值類型
  • .trim 自動過濾用戶輸入的首尾空格

鍵盤事件的修飾符

  • .enter
  • .tab
  • .delete (捕獲“刪除”和“退格”鍵)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

系統修飾鍵

  • .ctrl
  • .alt
  • .shift
  • .meta

鼠標按鈕修飾符

  • .left
  • .right
  • .middle

computed 的實現原理

computed 本質是一個惰性求值的觀察者。

computed 內部實現了一個惰性的 watcher,也就是 computed watcher,computed watcher 不會立刻求值,同時持有一個 dep 實例呕寝。

其內部通過 this.dirty 屬性標記計算屬性是否需要重新求值。

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

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

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

沒有的話,僅僅把 this.dirty = true孽江。 (當計算屬性依賴于其他數據時,屬性并不會立即重新計算番电,只有之后其他地方需要讀取屬性的時候岗屏,它才會真正計算,即具備 lazy(懶計算)特性漱办。)

v-model 的原理这刷?

我們在 vue 項目中主要使用 v-model 指令在表單 input、textarea娩井、select 等元素上創(chuàng)建雙向數據綁定暇屋,我們知道 v-model 本質上不過是語法糖,v-model 在內部為不同的輸入元素使用不同的屬性并拋出不同的事件:

  • text 和 textarea 元素使用 value 屬性和 input 事件洞辣;
  • checkbox 和 radio 使用 checked 屬性和 change 事件咐刨;
  • select 字段將 value 作為 prop 并將 change 作為事件。

以 input 表單元素為例:

<input v-model='something'>

相當于

<input v-bind:value="something" v-on:input="something = $event.target.value">
復制代碼

如果在自定義組件中扬霜,v-model 默認會利用名為 value 的 prop 和名為 input 的事件定鸟,如下所示:

父組件:
<ModelChild v-model="message"></ModelChild>

子組件:
<div>{{value}}</div>

props:{
    value: String
},
methods: {
  test1(){
     this.$emit('input', '小紅')
  },
},

computed 和 watch 的區(qū)別和運用的場景?

computed: 是計算屬性著瓶,依賴其它屬性值联予,并且 computed 的值有緩存,只有它依賴的屬性值發(fā)生改變,下一次獲取 computed 的值時才會重新計算 computed 的值躯泰;

watch: 更多的是「觀察」的作用谭羔,類似于某些數據的監(jiān)聽回調 ,每當監(jiān)聽的數據變化時都會執(zhí)行回調進行后續(xù)操作麦向;

運用場景:

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

虛擬 DOM 的優(yōu)缺點暖眼?

優(yōu)點:

  • 保證性能下限: 框架的虛擬 DOM 需要適配任何上層 API 可能產生的操作惕耕,它的一些 DOM 操作的實現必須是普適的,所以它的性能并不是最優(yōu)的诫肠;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虛擬 DOM 至少可以保證在你不需要手動優(yōu)化的情況下栋豫,依然可以提供還不錯的性能漱受,即保證性能的下限骡送;
  • 無需手動操作 DOM: 我們不再需要手動去操作 DOM昂羡,只需要寫好 View-Model 的代碼邏輯,框架會根據虛擬 DOM 和 數據雙向綁定摔踱,幫我們以可預期的方式更新視圖虐先,極大提高我們的開發(fā)效率;
  • 跨平臺: 虛擬 DOM 本質上是 JavaScript 對象,而 DOM 與平臺強相關派敷,相比之下虛擬 DOM 可以進行更方便地跨平臺操作蛹批,例如服務器渲染撰洗、weex 開發(fā)等等。

缺點:

  • 無法進行極致優(yōu)化: 雖然虛擬 DOM + 合理的優(yōu)化腐芍,足以應對絕大部分應用的性能需求差导,但在一些性能要求極高的應用中虛擬 DOM 無法進行針對性的極致優(yōu)化。

雙向數據綁定的原理

Vue.js 是采用數據劫持結合發(fā)布者-訂閱者模式的方式猪勇,通過Object.defineProperty()來劫持各個屬性的setter设褐,getter,在數據變動時發(fā)布消息給訂閱者泣刹,觸發(fā)相應的監(jiān)聽回調助析。主要分為以下幾個步驟:

  1. 需要observe的數據對象進行遞歸遍歷,包括子屬性對象的屬性椅您,都加上setter和getter這樣的話外冀,給這個對象的某個值賦值,就會觸發(fā)setter掀泳,那么就能監(jiān)聽到了數據變化
  2. compile解析模板指令雪隧,將模板中的變量替換成數據,然后初始化渲染頁面視圖员舵,并將每個指令對應的節(jié)點綁定更新函數脑沿,添加監(jiān)聽數據的訂閱者,一旦數據有變動固灵,收到通知,更新視圖
  3. Watcher訂閱者是Observer和Compile之間通信的橋梁劫流,主要做的事情是: ①在自身實例化時往屬性訂閱器(dep)里面添加自己 ②自身必須有一個update()方法 ③待屬性變動dep.notice()通知時巫玻,能調用自身的update()方法,并觸發(fā)Compile中綁定的回調祠汇,則功成身退仍秤。
  4. MVVM作為數據綁定的入口,整合Observer可很、Compile和Watcher三者诗力,通過Observer來監(jiān)聽自己的model數據變化,通過Compile來解析編譯模板指令我抠,最終利用Watcher搭起Observer和Compile之間的通信橋梁苇本,達到數據變化 -> 視圖更新;視圖交互變化(input) -> 數據model變更的雙向綁定效果菜拓。

Vue 中的 key 到底有什么用瓣窄?

key 是給每一個 vnode 的唯一 id,依靠 key,我們的 diff 操作可以更準確、更快速 (對于簡單列表頁渲染來說 diff 節(jié)點也更快,但會產生一些隱藏的副作用,比如可能不會產生過渡效果,或者在某些節(jié)點有綁定數據(表單)狀態(tài)纳鼎,會出現狀態(tài)錯位俺夕。)

diff 算法的過程中,先會進行新舊節(jié)點的首尾交叉對比,當無法匹配的時候會用新節(jié)點的 key 與舊節(jié)點進行比對,從而找到相應舊節(jié)點.

更準確 : 因為帶 key 就不是就地復用了,在 sameNode 函數 a.key === b.key 對比中可以避免就地復用的情況裳凸。所以會更加準確,如果不加 key,會導致之前節(jié)點的狀態(tài)被保留下來,會產生一系列的 bug。

更快速 : key 的唯一性可以被 Map 數據結構充分利用,相比于遍歷查找的時間復雜度 O(n),Map 的時間復雜度僅僅為 O(1),源碼如下:

function createKeyToOldIdx(children, beginIdx, endIdx) {
  let i, key;
  const map = {};
  for (i = beginIdx; i <= endIdx; ++i) {
    key = children[i].key;
    if (isDef(key)) map[key] = i;
  }
  return map;
}

你有對 Vue 項目進行哪些優(yōu)化劝贸?

(1)代碼層面的優(yōu)化

  • v-if 和 v-show 區(qū)分使用場景
  • computed 和 watch 區(qū)分使用場景
  • v-for 遍歷必須為 item 添加 key姨谷,且避免同時使用 v-if
  • 長列表性能優(yōu)化
  • 事件的銷毀
  • 圖片資源懶加載
  • 路由懶加載
  • 第三方插件的按需引入
  • 優(yōu)化無限列表性能
  • 服務端渲染 SSR or 預渲染

(2)Webpack 層面的優(yōu)化

  • Webpack 對圖片進行壓縮
  • 減少 ES6 轉為 ES5 的冗余代碼
  • 提取公共代碼
  • 模板預編譯
  • 提取組件的 CSS
  • 優(yōu)化 SourceMap
  • 構建結果輸出分析
  • Vue 項目的編譯優(yōu)化

(3)基礎的 Web 技術的優(yōu)化

  • 開啟 gzip 壓縮
  • 瀏覽器緩存
  • CDN 的使用
  • 使用 Chrome Performance 查找性能瓶頸

如何在組件中重復使用Vuex的mutation

使用mapMutations輔助函數,在組件中這么使用

import { mapMutations } from 'vuex'
methods:{
    ...mapMutations({
        setNumber:'SET_NUMBER',
    })
}
復制代碼

然后調用this.setNumber(10)相當調用this.$store.commit('SET_NUMBER',10)

v-for 為什么要加 key

如果不使用 key,Vue 會使用一種最大限度減少動態(tài)元素并且盡可能的嘗試就地修改/復用相同類型元素的算法映九。key 是為 Vue 中 vnode 的唯一標記梦湘,通過這個 key,我們的 diff 操作可以更準確氯迂、更快速

更準確:因為帶 key 就不是就地復用了践叠,在 sameNode 函數 a.key === b.key 對比中可以避免就地復用的情況。所以會更加準確嚼蚀。

更快速:利用 key 的唯一性生成 map 對象來獲取對應節(jié)點禁灼,比遍歷方式更快

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市轿曙,隨后出現的幾起案子弄捕,更是在濱河造成了極大的恐慌,老刑警劉巖导帝,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件守谓,死亡現場離奇詭異,居然都是意外死亡您单,警方通過查閱死者的電腦和手機幻工,發(fā)現死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門存淫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事饼疙《恚” “怎么了巫俺?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵偎谁,是天一觀的道長。 經常有香客問我俺驶,道長幸逆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任暮现,我火速辦了婚禮还绘,結果婚禮上,老公的妹妹穿的比我還像新娘栖袋。我一直安慰自己蚕甥,他們只是感情好,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布栋荸。 她就那樣靜靜地躺著菇怀,像睡著了一般凭舶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爱沟,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天帅霜,我揣著相機與錄音,去河邊找鬼呼伸。 笑死身冀,一個胖子當著我的面吹牛,可吹牛的內容都是我干的括享。 我是一名探鬼主播搂根,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼铃辖!你這毒婦竟也來了剩愧?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤娇斩,失蹤者是張志新(化名)和其女友劉穎仁卷,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體犬第,經...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡锦积,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了歉嗓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丰介。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鉴分,靈堂內的尸體忽然破棺而出哮幢,到底是詐尸還是另有隱情,我是刑警寧澤冠场,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布家浇,位于F島的核電站本砰,受9級特大地震影響碴裙,放射性物質發(fā)生泄漏。R本人自食惡果不足惜点额,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一舔株、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧还棱,春花似錦载慈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辞做。三九已至,卻和暖如春寡具,著一層夾襖步出監(jiān)牢的瞬間秤茅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工童叠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留框喳,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓厦坛,卻偏偏與公主長得像五垮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子杜秸,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容