Vue
1.1 怎樣理解 Vue 的單向數(shù)據(jù)流铲咨?
- 數(shù)據(jù)從父級(jí)組件傳遞給子組件卧秘,只能單向綁定
- 子組件內(nèi)部不能直接修改從父級(jí)傳遞過(guò)來(lái)的數(shù)據(jù)
- 所有的 prop 都使得其父子 prop 之間形成了一個(gè)單向下行綁定:父級(jí) prop 的更新會(huì)向下流動(dòng)到子組件中,但是反過(guò)來(lái)則不行包晰,這樣會(huì)防止從子組件意外改變父級(jí)組件的狀態(tài)顷歌, 從而導(dǎo)致你的應(yīng)用的數(shù)據(jù)流向難以理解。
- 每次父級(jí)組件發(fā)生更新時(shí)锣险,子組件中所有的 prop 都將會(huì)刷新為最新的值,這意味著你不應(yīng)該在一個(gè)子組件內(nèi)部改變 prop览闰。如果你這樣做了芯肤,Vue 會(huì)在瀏覽器的控制臺(tái)中發(fā)出警 告
- 子組件想修改時(shí),只能通過(guò) $emit 派發(fā)一個(gè)自定義事件压鉴,父組件接收到后崖咨,由父組件 修改
1.2 談?wù)勀銓?duì) Vue 生命周期的理解?
(1)生命周期是什么油吭?
Vue 實(shí)例有一個(gè)完整的生命周期击蹲,也就是從開(kāi)始創(chuàng)建、初始化數(shù)據(jù)婉宰、編譯模版歌豺、掛載 Dom -> 渲染、更新 -> 渲染心包、卸載等一系列過(guò)程类咧,我們稱(chēng)這是 Vue 的生命周期
(2)各個(gè)生命周期的作用
beforeCreate | 組件實(shí)例被創(chuàng)建之初,組件的屬性生效之前 |
---|---|
created | 組件實(shí)例已經(jīng)完全創(chuàng)建,屬性也綁定痕惋,但真實(shí) dom 還沒(méi)有生成区宇,$el 還不可用 |
beforeMount | 在掛載開(kāi)始之前被調(diào)用:相關(guān)的 render 函數(shù)首次被調(diào)用 |
mounted | el 被新創(chuàng)建的 vm.$el 替換,并掛載到實(shí)例上去之后調(diào)用該鉤子 |
beforeUpdate | 組件數(shù)據(jù)更新之前調(diào)用值戳,發(fā)生在虛擬 DOM 打補(bǔ)丁之前 |
update | 組件數(shù)據(jù)更新之后 |
activited | keep-alive 專(zhuān)屬议谷,組件被激活時(shí)調(diào)用 |
deadctivated | keep-alive 專(zhuān)屬,組件被銷(xiāo)毀時(shí)調(diào)用 |
beforeDestory | 組件銷(xiāo)毀前調(diào)用 |
destoryed | 組件銷(xiāo)毀后調(diào)用 |
1.3 談?wù)勀銓?duì) keep-alive 的了解堕虹?
keep-alive 是 Vue 內(nèi)置的一個(gè)組件卧晓,可以使被包含的組件保留狀態(tài),避免重新渲染 鲫凶,其有以下特性:
- 一般結(jié)合路由和動(dòng)態(tài)組件一起使用禀崖,用于緩存組件
- 提供 include 和 exclude 屬性,兩者都支持字符串或正則表達(dá)式螟炫, include 表示只有名稱(chēng)匹配的組件會(huì)被緩存波附,exclude 表示任何名稱(chēng)匹配的組件都不會(huì)被緩存 ,其中 exclude 的優(yōu)先級(jí)比 include 高
- 對(duì)應(yīng)兩個(gè)鉤子函數(shù) activated 和 deactivated 昼钻,當(dāng)組件被激活時(shí)掸屡,觸發(fā)鉤子函數(shù) activated,當(dāng)組件被移除時(shí)然评,觸發(fā)鉤子函數(shù) deactivated
1.4 組件中 data 為什么是一個(gè)函數(shù)仅财?
因?yàn)榻M件是用來(lái)復(fù)用的,且 JS 里對(duì)象是引用關(guān)系碗淌,如果組件中 data 是一個(gè)對(duì)象盏求,那么這樣作用域沒(méi)有隔離,子組件中的 data 屬性值會(huì)相互影響
如果組件中 data 選項(xiàng)是一個(gè)函數(shù)亿眠,那么每個(gè)實(shí)例可以維護(hù)一份被返回對(duì)象的獨(dú)立的拷貝碎罚,組件實(shí)例之間的 data 屬性值不會(huì)互相影響;而 new Vue 的實(shí)例纳像,是不會(huì)被復(fù)用的荆烈,因此不存在引用對(duì)象的問(wèn)題
1.5 你對(duì)vue項(xiàng)目哪些優(yōu)化?
(1)代碼層面的優(yōu)化
- v-if 和 v-show 區(qū)分使用場(chǎng)景
- computed 和 watch 區(qū)分使用場(chǎng)景
- v-for 遍歷必須為 item 添加 key竟趾,且避免同時(shí)使用 v-if
- 長(zhǎng)列表性能優(yōu)化
- 事件的銷(xiāo)毀
- 圖片資源懶加載
- 路由懶加載
- 第三方插件的按需引入
- 優(yōu)化無(wú)限列表性能
- 服務(wù)端渲染 SSR or 預(yù)渲染
(2)Webpack 層面的優(yōu)化
- Webpack 對(duì)圖片進(jìn)行壓縮
- 減少 ES6 轉(zhuǎn)為 ES5 的冗余代碼
- 提取公共代碼
- 模板預(yù)編譯
- 提取組件的 CSS
- 優(yōu)化 SourceMap
- 構(gòu)建結(jié)果輸出分析
- Vue 項(xiàng)目的編譯優(yōu)化
(3)基礎(chǔ)的 Web 技術(shù)的優(yōu)化
- 開(kāi)啟 gzip 壓縮
- 瀏覽器緩存
- CDN 的使用
- 使用 Chrome Performance 查找性能瓶頸
1.6 vue中的key有什么作用憔购?
key 是為 Vue 中 vnode 的唯一標(biāo)記,通過(guò)這個(gè) key岔帽,我們的 diff 操作可以更準(zhǔn)確玫鸟、更快速
Vue 的 diff 過(guò)程可以概括為:oldCh 和 newCh 各有兩個(gè)頭尾的變量 oldStartIndex、oldEndIndex 和 newStartIndex山卦、newEndIndex鞋邑,它們會(huì)新節(jié)點(diǎn)和舊節(jié)點(diǎn)會(huì)進(jìn)行兩兩對(duì)比诵次,即一共有4種比較方式:newStartIndex 和oldStartIndex 账蓉、newEndIndex 和 oldEndIndex 枚碗、newStartIndex 和 oldEndIndex 、newEndIndex 和 oldStartIndex铸本,如果以上 4 種比較都沒(méi)匹配肮雨,如果設(shè)置了key,就會(huì)用 key 再進(jìn)行比較箱玷,在比較的過(guò)程中怨规,遍歷會(huì)往中間靠,一旦 StartIdx > EndIdx 表明 oldCh 和 newCh 至少有一個(gè)已經(jīng)遍歷完了锡足,就會(huì)結(jié)束比較
所以 Vue 中 key 的作用是:key 是為 Vue 中 vnode 的唯一標(biāo)記波丰,通過(guò)這個(gè) key,我們的 diff 操作可以更準(zhǔn)確舶得、更快速
1.7 虛擬dom的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 保證性能下限: 框架的虛擬 DOM 需要適配任何上層 API 可能產(chǎn)生的操作掰烟,它的一些 DOM 操作的實(shí)現(xiàn)必須是普適的,所以它的性能并不是最優(yōu)的沐批;但是比起粗暴的 DOM 操作性能要好很多纫骑,因此框架的虛擬 DOM 至少可以保證在你不需要手動(dòng)優(yōu)化的情況下,依然可以提供還不錯(cuò)的性能九孩,即保證性能的下限先馆;
- 無(wú)需手動(dòng)操作 DOM: 我們不再需要手動(dòng)去操作 DOM,只需要寫(xiě)好 View-Model 的代碼邏輯躺彬,框架會(huì)根據(jù)虛擬 DOM 和 數(shù)據(jù)雙向綁定煤墙,幫我們以可預(yù)期的方式更新視圖,極大提高我們的開(kāi)發(fā)效率宪拥;
- 跨平臺(tái): 虛擬 DOM 本質(zhì)上是 JavaScript 對(duì)象,而 DOM 與平臺(tái)強(qiáng)相關(guān)仿野,相比之下虛擬 DOM 可以進(jìn)行更方便地跨平臺(tái)操作,例如服務(wù)器渲染江解、weex 開(kāi)發(fā)等等
缺點(diǎn):
無(wú)法進(jìn)行極致優(yōu)化: 雖然虛擬 DOM + 合理的優(yōu)化设预,足以應(yīng)對(duì)絕大部分應(yīng)用的性能需求,但在一些性能要求極高的應(yīng)用中虛擬 DOM 無(wú)法進(jìn)行針對(duì)性的極致優(yōu)化:比如動(dòng)畫(huà)等等
1.8 虛擬dom實(shí)現(xiàn)原理犁河?
虛擬 DOM 的實(shí)現(xiàn)原理主要包括以下 3 部分:
- 用 JavaScript 對(duì)象模擬真實(shí) DOM 樹(shù)鳖枕,對(duì)真實(shí) DOM 進(jìn)行抽象;
- diff 算法 — 比較兩棵虛擬 DOM 樹(shù)的差異桨螺;
- pach 算法 — 將兩個(gè)虛擬 DOM 對(duì)象的差異應(yīng)用到真正的 DOM 樹(shù)
1.9 Vue 是如何實(shí)現(xiàn)數(shù)據(jù)雙向綁定的宾符?
Vue 數(shù)據(jù)雙向綁定主要是指:數(shù)據(jù)變化更新視圖
- 輸入框內(nèi)容變化時(shí),Data 中的數(shù)據(jù)同步變化灭翔。即 View => Data 的變化魏烫。
- Data 中的數(shù)據(jù)變化時(shí),文本節(jié)點(diǎn)的內(nèi)容同步變化。即 Data => View 的變化
Vue 主要通過(guò)以下 4 個(gè)步驟來(lái)實(shí)現(xiàn)數(shù)據(jù)雙向綁定的:
- 實(shí)現(xiàn)一個(gè)監(jiān)聽(tīng)器 Observer:對(duì)數(shù)據(jù)對(duì)象進(jìn)行遍歷哄褒,包括子屬性對(duì)象的屬性稀蟋,利用 Object.defineProperty() 對(duì)屬性都加上 setter 和 getter。這樣的話(huà)呐赡,給這個(gè)對(duì)象的某個(gè)值賦值退客,就會(huì)觸發(fā) setter,那么就能監(jiān)聽(tīng)到了數(shù)據(jù)變化
- 實(shí)現(xiàn)一個(gè)解析器 Compile:解析 Vue 模板指令链嘀,將模板中的變量都替換成數(shù)據(jù)萌狂,然后初始化渲染頁(yè)面視圖,并將每個(gè)指令對(duì)應(yīng)的節(jié)點(diǎn)綁定更新函數(shù)怀泊,添加監(jiān)聽(tīng)數(shù)據(jù)的訂閱者茫藏,一旦數(shù)據(jù)有變動(dòng),收到通知霹琼,調(diào)用更新函數(shù)進(jìn)行數(shù)據(jù)更新
- 實(shí)現(xiàn)一個(gè)訂閱者 Watcher:Watcher 訂閱者是 Observer 和 Compile 之間通信的橋梁 务傲,主要的任務(wù)是訂閱 Observer 中的屬性值變化的消息,當(dāng)收到屬性值變化的消息時(shí)碧囊,觸發(fā)解析器 Compile 中對(duì)應(yīng)的更新函
- 實(shí)現(xiàn)一個(gè)訂閱器 Dep:訂閱器采用 發(fā)布-訂閱 設(shè)計(jì)模式树灶,用來(lái)收集訂閱者 Watcher,對(duì)監(jiān)聽(tīng)器 Observer 和 訂閱者 Watcher 進(jìn)行統(tǒng)一管理