Vue前端基礎(chǔ)知識(shí)



0.那你能講一講 MVVM 嗎褥符?

MVVM 是 Model-View-ViewModel 縮寫,也就是把 MVC 中的 Controller 演變成 ViewModel嵌赠。Model 層代表數(shù)據(jù)模型畅买,View 代表 UI 組件同仆,ViewModel 是 View 和 Model 層的橋梁混巧,數(shù)據(jù)會(huì)綁定到 viewModel 層并自動(dòng)將數(shù)據(jù)渲染到頁(yè)面中枪向,視圖變化的時(shí)候會(huì)通知 viewModel 層更新數(shù)據(jù)。

1.簡(jiǎn)單說(shuō)一下 Vue2.x 響應(yīng)式數(shù)據(jù)原理

Vue 在初始化數(shù)據(jù)時(shí)咧党,會(huì)使用 Object.defineProperty 重新定義 data 中的所有屬性遣疯,當(dāng)頁(yè)面使用對(duì)應(yīng)屬性時(shí),首先會(huì)進(jìn)行依賴收集(收集當(dāng)前組件的 watcher)如果屬性發(fā)生變化會(huì)通知相關(guān)依賴進(jìn)行更新操作(發(fā)布訂閱)凿傅。

2.那你知道 Vue3.x 響應(yīng)式數(shù)據(jù)原理嗎?

Vue3.x 改用 Proxy 替代 Object.defineProperty数苫。因?yàn)?Proxy 可以直接監(jiān)聽對(duì)象和數(shù)組的變化聪舒,并且有多達(dá) 13 種攔截方法。并且作為新標(biāo)準(zhǔn)將受到瀏覽器廠商重點(diǎn)持續(xù)的性能優(yōu)化虐急。

*Proxy 只會(huì)代理對(duì)象的第一層箱残,那么 Vue3 又是怎樣處理這個(gè)問(wèn)題的呢?

判斷當(dāng)前 Reflect.get 的返__值是否為 Object止吁,如果是則再通過(guò) reactive 方法做代理被辑,這樣就實(shí)現(xiàn)了深度觀測(cè)。

*監(jiān)測(cè)數(shù)組的時(shí)候可能觸發(fā)多次 get/set敬惦,那么如何防止觸發(fā)多次呢盼理?

我們可以判斷 key 是否為當(dāng)前被代理對(duì)象 target 自身屬性,也可以判斷舊值與新值是否相等俄删,只有滿足以上兩個(gè)條件之一時(shí)宏怔,才有可能執(zhí)行 trigger奏路。

3.再說(shuō)一下 vue2.x 中如何監(jiān)測(cè)數(shù)組變化

使用了函數(shù)劫持的方式,重寫了數(shù)組的方法臊诊,Vue 將 data 中的數(shù)組進(jìn)行了原型鏈重寫鸽粉,指向了自己定義的數(shù)組原型方法。這樣當(dāng)調(diào)用數(shù)組 api 時(shí)抓艳,可以通知依賴更新触机。如果數(shù)組中包含著引用類型,會(huì)對(duì)數(shù)組中的引用類型再次遞歸遍歷進(jìn)行監(jiān)控玷或。這樣就實(shí)現(xiàn)了監(jiān)測(cè)數(shù)組變化儡首。

4.nextTick 知道嗎,實(shí)現(xiàn)原理是什么庐椒?

在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)椒舵。nextTick 主要使用了宏任務(wù)和微任務(wù)。根據(jù)執(zhí)行環(huán)境分別嘗試采用

* Promise

* Mutation

* Observerset

* Immediate

如果以上都不行則采用 setTimeout

定義了一個(gè)異步方法约谈,多次調(diào)用 nextTick 會(huì)將方法存入隊(duì)列中笔宿,通過(guò)這個(gè)異;步方法清空當(dāng)前隊(duì)

5.說(shuō)一下 Vue 的生命周期

beforeCreate 是 new Vue()之后觸發(fā)的第一個(gè)鉤子棱诱,在當(dāng)前階段 data泼橘、methods、computed 以及 watch 上的數(shù)據(jù)和方法都不能被訪問(wèn)迈勋。

created 在實(shí)例創(chuàng)建完成后發(fā)生炬灭,當(dāng)前階段已經(jīng)完成了數(shù)據(jù)觀測(cè),也就是可以使用數(shù)據(jù)靡菇,更改數(shù)據(jù)重归,在這里更改數(shù)據(jù)不會(huì)觸發(fā) updated 函數(shù)∠梅铮可以做一些初始數(shù)據(jù)的獲取鼻吮,在當(dāng)前階段無(wú)法與 Dom 進(jìn)行交互,如果非要想较鼓,可以通過(guò) vm.$nextTick來(lái)訪問(wèn)Dom椎木。

beforeMount發(fā)生在掛載之前,在這之前template模板已導(dǎo)入渲染函數(shù)編譯博烂。而當(dāng)前階段虛擬Dom已經(jīng)創(chuàng)建完成香椎,即將開始渲染。在此時(shí)也可以對(duì)數(shù)據(jù)進(jìn)行更改禽篱,不會(huì)觸發(fā)updated畜伐。

mounted在掛載完成后發(fā)生,在當(dāng)前階段谆级,真實(shí)的Dom掛載完畢烤礁,數(shù)據(jù)完成雙向綁定讼积,可以訪問(wèn)到Dom節(jié)點(diǎn),使用$refs 屬性對(duì) Dom 進(jìn)行操作脚仔。

beforeUpdate 發(fā)生在更新之前勤众,也就是響應(yīng)式數(shù)據(jù)發(fā)生更新,虛擬 dom 重新渲染之前被觸發(fā)鲤脏,你可以在當(dāng)前階段進(jìn)行更改數(shù)據(jù)们颜,不會(huì)造成重渲染。

updated 發(fā)生在更新完成之后猎醇,當(dāng)前階段組件 Dom 已完成更新窥突。要注意的是避免在此期間更改數(shù)據(jù),因?yàn)檫@可能會(huì)導(dǎo)致無(wú)限循環(huán)的更新硫嘶。

beforeDestroy 發(fā)生在實(shí)例銷毀之前阻问,在當(dāng)前階段實(shí)例完全可以被使用,我們可以在這時(shí)進(jìn)行善后收尾工作沦疾,比如清除計(jì)時(shí)器称近。

destroyed 發(fā)生在實(shí)例銷毀之后,這個(gè)時(shí)候只剩下了 dom 空殼哮塞。組件已被拆解刨秆,數(shù)據(jù)綁定被卸除,監(jiān)聽被移出忆畅,子實(shí)例也統(tǒng)統(tǒng)被銷毀衡未。

6.你的接口請(qǐng)求一般放在哪個(gè)生命周期中?

接口請(qǐng)求一般放在 mounted 中家凯,但需要注意的是服務(wù)端渲染時(shí)不支持 mounted缓醋,需要放到 created 中。

7.再說(shuō)一下 Computed 和 Watch

Computed 本質(zhì)是一個(gè)具備緩存的 watcher绊诲,依賴的屬性發(fā)生變化就會(huì)更新視圖改衩。

適用于計(jì)算比較消耗性能的計(jì)算場(chǎng)景。當(dāng)表達(dá)式過(guò)于復(fù)雜時(shí)驯镊,在模板中放入過(guò)多邏輯會(huì)讓模板難以維護(hù),可以將復(fù)雜的邏輯放入計(jì)算屬性中處理竭鞍。

Watch 沒(méi)有緩存性板惑,更多的是觀察的作用,可以監(jiān)聽某些數(shù)據(jù)執(zhí)行回調(diào)偎快。當(dāng)我們需要深度監(jiān)聽對(duì)象中的屬性時(shí)冯乘,可以打開 deep:true 選項(xiàng),這樣便會(huì)對(duì)對(duì)象中的每一項(xiàng)進(jìn)行監(jiān)聽晒夹。這樣會(huì)帶來(lái)性能問(wèn)題裆馒,優(yōu)化的話可以使用字符串形式監(jiān)聽姊氓,如果沒(méi)有寫到組件中,不要忘記使用 unWatch 手動(dòng)注銷哦喷好。

8.說(shuō)一下 v-if 和 v-show 的區(qū)別

當(dāng)條件不成立時(shí)翔横,v-if 不會(huì)渲染 DOM 元素,v-show 操作的是樣式(display)梗搅,切換當(dāng)前 DOM 的顯示和隱藏禾唁。

9.組件中的 data 為什么是一個(gè)函數(shù)?

一個(gè)組件被復(fù)用多次的話无切,也就會(huì)創(chuàng)建多個(gè)實(shí)例荡短。本質(zhì)上,這些實(shí)例用的都是同一個(gè)構(gòu)造函數(shù)哆键。如果 data 是對(duì)象的話掘托,對(duì)象屬于引用類型,會(huì)影響到所有的實(shí)例籍嘹。所以為了保證組件不同的實(shí)例之間 data 不沖突闪盔,data 必須是一個(gè)函數(shù)。

10.說(shuō)一下 v-model 的原理

v-model 本質(zhì)就是一個(gè)語(yǔ)法糖噩峦,可以看成是 value + input 方法的語(yǔ)法糖锭沟。

可以通過(guò) model 屬性的 prop 和 event 屬性來(lái)進(jìn)行自定義。原生的 v-model识补,會(huì)根據(jù)標(biāo)簽的不同生成不同的事件和屬性族淮。

11.Vue 事件綁定原理說(shuō)一下

原生事件綁定是通過(guò) addEventListener 綁定給真實(shí)元素的,組件事件綁定是通過(guò) Vue 自定義的$on 實(shí)現(xiàn)的凭涂。

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

簡(jiǎn)單說(shuō)切油,Vue 的編譯過(guò)程就是將 template 轉(zhuǎn)化為 render 函數(shù)的過(guò)程蝙斜。會(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)化過(guò)程就是深度遍歷 AST 樹,按照相關(guān)條件對(duì)樹節(jié)點(diǎn)進(jìn)行標(biāo)記受楼。這些被標(biāo)記的節(jié)點(diǎn)(靜態(tài)節(jié)點(diǎn))我們就可以跳過(guò)對(duì)它們的比對(duì)垦搬,對(duì)運(yùn)行時(shí)的模板起到很大的優(yōu)化作用呼寸。

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

13.Vue2.x 和 Vue3.x 渲染器的 diff 算法分別說(shuō)一下

簡(jiǎn)單來(lái)說(shuō)猴贰,diff 算法有以下過(guò)程

*同級(jí)比較对雪,再比較子節(jié)點(diǎn)

*先判斷一方有子節(jié)點(diǎn)一方?jīng)]有子節(jié)點(diǎn)的情況(如果新的 children 沒(méi)有子節(jié)點(diǎn),將舊的子節(jié)點(diǎn)移除)

*比較都有子節(jié)點(diǎn)的情況(核心 diff)

*遞歸比較子節(jié)點(diǎn)

正常 Diff 兩個(gè)樹的時(shí)間復(fù)雜度是 O(n^3)糟趾,但實(shí)際情況下我們很少會(huì)進(jìn)行跨層級(jí)的移動(dòng) DOM慌植,所以 Vue 將 Diff 進(jìn)行了優(yōu)化,從 O(n^3) -> O(n)义郑,只有當(dāng)新舊 children 都為多個(gè)子節(jié)點(diǎn)時(shí)才需要用核心的 Diff 算法進(jìn)行同層級(jí)比較蝶柿。

Vue2 的核心 Diff 算法采用了雙端比較的算法,同時(shí)從新舊 children 的兩端開始進(jìn)行比較非驮,借助 key 值找到可復(fù)用的節(jié)點(diǎn)交汤,再進(jìn)行相關(guān)操作。相比 React 的 Diff 算法劫笙,同樣情況下可以減少移動(dòng)節(jié)點(diǎn)次數(shù)芙扎,減少不必要的性能損耗,更加的優(yōu)雅填大。

Vue3.x 借鑒了ivi 算法和 inferno 算法

在創(chuàng)建 VNode 時(shí)就確定其類型戒洼,以及在 mount/patch 的過(guò)程中采用位運(yùn)算來(lái)判斷一個(gè) VNode 的類型,在這個(gè)基礎(chǔ)之上再配合核心的 Diff 算法允华,使得性能上較 Vue2.x 有了提升圈浇。

該算法中還運(yùn)用了動(dòng)態(tài)規(guī)劃的思想求解最長(zhǎng)遞歸子序列航罗。

14.再說(shuō)一下虛擬 Dom 以及 key 屬性的作用

由于在瀏覽器中操作 DOM 是很昂貴的瞄勾。頻繁的操作 DOM,會(huì)產(chǎn)生一定的性能問(wèn)題鹤盒。這就是虛擬 Dom 的產(chǎn)生原因百炬。

Vue2 的 Virtual DOM 借鑒了開源庫(kù) snabbdom 的實(shí)現(xiàn)褐隆。

Virtual DOM 本質(zhì)就是用一個(gè)原生的 JS 對(duì)象去描述一個(gè) DOM 節(jié)點(diǎn)。是對(duì)真實(shí) DOM 的一層抽象剖踊。(也就是源碼中的 VNode 類庶弃,它定義在 src/core/vdom/vnode.js 中。)

VirtualDOM 映射到真實(shí) DOM 要經(jīng)歷 VNode 的 create德澈、diff虫埂、patch 等階段。

「key 的作用是盡可能的復(fù)用 DOM 元素圃验。」

新舊 children 中的節(jié)點(diǎn)只有順序是不同的時(shí)候缝呕,最佳的操作應(yīng)該是通過(guò)移動(dòng)元素的位置來(lái)達(dá)到更新的目的澳窑。

需要在新舊 children 的節(jié)點(diǎn)中保存映射關(guān)系斧散,以便能夠在舊 children 的節(jié)點(diǎn)中找到可復(fù)用的節(jié)點(diǎn)。key 也就是 children 中節(jié)點(diǎn)的唯一標(biāo)識(shí)摊聋。

15.keep-alive 了解嗎

keep-alive 可以實(shí)現(xiàn)組件緩存鸡捐,當(dāng)組件切換時(shí)不會(huì)對(duì)當(dāng)前組件進(jìn)行卸載。

常用的兩個(gè)屬性 include/exclude麻裁,允許組件有條件的進(jìn)行緩存箍镜。

兩個(gè)生命周期 activated/deactivated,用來(lái)得知當(dāng)前組件是否處于活躍狀態(tài)煎源。

keep-alive 的中還運(yùn)用了 LRU(Least Recently Used)算法色迂。

16.Vue 中組件生命周期調(diào)用順序說(shuō)一下

組件的調(diào)用順序都是先父后子,渲染完成的順序是先子后父。

組件的銷毀操作是先父后子手销,銷毀完成的順序是先子后父歇僧。

加載渲染過(guò)程

父 beforeCreate->父 created->父 beforeMount->子 beforeCreate->子 created->子 beforeMount- >子 mounted->父 mounted

子組件更新過(guò)程

父 beforeUpdate->子 beforeUpdate->子 updated->父 updated

父組件更新過(guò)程

父 beforeUpdate -> 父 updated

銷毀過(guò)程

父 beforeDestroy->子 beforeDestroy->子 destroyed->父 destroyed

17.Vue2.x 組件通信有哪些方式?

父子組件通信

父->子 props锋拖,子->父 $on诈悍、$emit

獲取父子組件實(shí)例 $parent、$children

Ref 獲取實(shí)例的方式調(diào)用組件的屬性或者方法

Provide兽埃、inject 官方不推薦使用侥钳,但是寫組件庫(kù)時(shí)很常用

兄弟組件通信

Event Bus 實(shí)現(xiàn)跨組件通信 Vue.prototype.$bus = new Vue

Vuex

跨級(jí)組件通信

Vuex

$attrs、$listeners

Provide柄错、inject

18.SSR 了解嗎舷夺?

SSR 也就是服務(wù)端渲染,也就是將 Vue 在客戶端把標(biāo)簽渲染成 HTML 的工作放在服務(wù)端完成鄙陡,然后再把 html 直接返回給客戶端冕房。

SSR 有著更好的 SEO、并且首屏加載速度更快等優(yōu)點(diǎn)趁矾。不過(guò)它也有一些缺點(diǎn)耙册,比如我們的開發(fā)條件會(huì)受到限制,服務(wù)器端渲染只支持 beforeCreate 和 created 兩個(gè)鉤子毫捣,當(dāng)我們需要一些外部擴(kuò)展庫(kù)時(shí)需要特殊處理详拙,服務(wù)端渲染應(yīng)用程序也需要處于 Node.js 的運(yùn)行環(huán)境。還有就是服務(wù)器會(huì)有更大的負(fù)載需求蔓同。

19.你都做過(guò)哪些 Vue 的性能優(yōu)化饶辙?

編碼階段

*盡量減少 data 中的數(shù)據(jù),data 中的數(shù)據(jù)都會(huì)增加 getter 和 setter斑粱,會(huì)收集對(duì)應(yīng)的 watcherv-if 和 v-for 不能連用

*如果需要使用 v-for 給每項(xiàng)元素綁定事件時(shí)使用事件代理

*SPA 頁(yè)面采用 keep-alive 緩存組件

*在更多的情況下弃揽,使用 v-if 替代 v-show

*key 保證唯一

*使用路由懶加載、異步組件

*防抖、節(jié)流

*第三方模塊按需導(dǎo)入

*長(zhǎng)列表滾動(dòng)到可視區(qū)域動(dòng)態(tài)加載

*圖片懶加載

SEO 優(yōu)化

*預(yù)渲染服務(wù)端渲染

*SSR

打包優(yōu)化

*壓縮代碼

*Tree Shaking/Scope Hoisting

*使用 cdn 加載第三方模塊

*多線程打包 happypack

*splitChunks 抽離公共文

*sourceMap

優(yōu)化用戶體驗(yàn)

*骨架屏

*PWA

還可以使用緩存(客戶端緩存矿微、服務(wù)端緩存)優(yōu)化痕慢、服務(wù)端開啟 gzip 壓縮等。

20.hash 路由和 history 路由實(shí)現(xiàn)原理說(shuō)一下

location.hash 的值實(shí)際就是 URL 中#后面的東西涌矢。

history 實(shí)際采用了 HTML5 中提供的 API 來(lái)實(shí)現(xiàn)掖举,主要有 history.pushState()和 history.replaceState()。

21.了解過(guò)(用過(guò))react或者angular嗎娜庇,他們有什么區(qū)別塔次?

Vue 借鑒了 angular 的模板和數(shù)據(jù)綁定技術(shù),又借鑒了 react 的組件化和虛擬 DOM 技術(shù)名秀。

22.那首先談?wù)勀銓?duì)Vue的理解吧励负?

關(guān)鍵點(diǎn):漸進(jìn)式 JavaScript 框架、核心庫(kù)加插件泰偿、動(dòng)態(tài)創(chuàng)建用戶界面(異步獲取后臺(tái)數(shù)據(jù)熄守,數(shù)據(jù)展示在界面)

特點(diǎn): MVVM 模式;代碼簡(jiǎn)潔體積小耗跛,運(yùn)行效率高裕照,適合移動(dòng)PC端開發(fā);本身只關(guān)注 UI (和 react 相似)调塌,可以輕松引入? Vue 插件或其他的第三方庫(kù)進(jìn)行開發(fā)晋南。

23.你剛剛說(shuō)到了MVVM,能詳細(xì)說(shuō)說(shuō)嗎羔砾?

全稱: Model-View-ViewModel 负间, Model 表示數(shù)據(jù)模型層。 view 表示視圖層姜凄, ViewModel 是 View 和 Model 層的橋梁政溃,數(shù)據(jù)綁定到 viewModel 層并自動(dòng)渲染到頁(yè)面中,視圖變化通知 viewModel 層更新數(shù)據(jù)态秧。

24.vue是如何實(shí)現(xiàn)響應(yīng)式數(shù)據(jù)的呢董虱?(響應(yīng)式數(shù)據(jù)原理)

Vue2: Object.defineProperty 重新定義 data 中所有的屬性, Object.defineProperty 可以使數(shù)據(jù)的獲取與設(shè)置增加一個(gè)攔截的功能申鱼,攔截屬性的獲取愤诱,進(jìn)行依賴收集。攔截屬性的更新操作捐友,進(jìn)行通知淫半。

具體的過(guò)程:首先Vue使用 initData 初始化用戶傳入的參數(shù),然后使用? new Observer 對(duì)數(shù)據(jù)進(jìn)行觀測(cè)匣砖,如果數(shù)據(jù)是一個(gè)對(duì)象類型就會(huì)調(diào)用 this.walk(value) 對(duì)對(duì)象進(jìn)行處理科吭,內(nèi)部使用? defineeReactive? 循環(huán)對(duì)象屬性定義響應(yīng)式變化昏滴,核心就是使用 Object.defineProperty 重新定義數(shù)據(jù)。

25.vue中是如何檢測(cè)數(shù)組變化的呢对人?

數(shù)組就是使用 object.defineProperty 重新定義數(shù)組的每一項(xiàng)影涉,那能引起數(shù)組變化的方法我們都是知道的, pop 规伐、 push 、 shift 匣缘、 unshift 猖闪、 splice 、 sort 肌厨、 reverse 這七種培慌,只要這些方法執(zhí)行改了數(shù)組內(nèi)容,我就更新內(nèi)容就好了柑爸,是不是很好理解吵护。

*是用來(lái)函數(shù)劫持的方式,重寫了數(shù)組方法表鳍,具體呢就是更改了數(shù)組的原型馅而,更改成自己的,用戶調(diào)數(shù)組的一些方法的時(shí)候譬圣,走的就是自己的方法瓮恭,然后通知視圖去更新。

*數(shù)組里每一項(xiàng)可能是對(duì)象厘熟,那么我就是會(huì)對(duì)數(shù)組的每一項(xiàng)進(jìn)行觀測(cè)屯蹦,(且只有數(shù)組里的對(duì)象才能進(jìn)行觀測(cè),觀測(cè)過(guò)的也不會(huì)進(jìn)行觀測(cè))

vue3:改用 proxy 绳姨,可直接監(jiān)聽對(duì)象數(shù)組的變化登澜。

26.Vue的事件綁定原理吧

*原生 DOM 的綁定:Vue在創(chuàng)建真實(shí)DOM時(shí)會(huì)調(diào)用 createElm ,默認(rèn)會(huì)調(diào)用 invokeCreateHooks 飘庄。會(huì)遍歷當(dāng)前平臺(tái)下相對(duì)的屬性處理代碼脑蠕,其中就有 updateDOMListeners 方法,內(nèi)部會(huì)傳入 add() 方法

*組件綁定事件竭宰,原生事件空郊,自定義事件;組件綁定之間是通過(guò)Vue中自定義的 $on 方法實(shí)現(xiàn)的切揭。

(可以理解為:組件的 nativeOnOn? 等價(jià)于 普通元素on 組件的on會(huì)單獨(dú)處理)

27.v-model中的實(shí)現(xiàn)原理及如何自定義v-model

v-model 可以看成是 value+input 方法的語(yǔ)法糖(組件)狞甚。原生的 v-model ,會(huì)根據(jù)標(biāo)簽的不同生成不同的事件與屬性廓旬。解析一個(gè)指令來(lái)哼审。

自定義:自己寫 model 屬性谐腰,里面放上 prop 和 event

28. 為什么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ì)列(異步)鸳慈。

29.了解nextTick嗎?

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

30.Vue的生命周期

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

1. beforeCreate :實(shí)例初始化之后彼念,數(shù)據(jù)觀測(cè)之前調(diào)用

2. created:實(shí)例創(chuàng)建萬(wàn)之后調(diào)用挪圾。實(shí)例完成:數(shù)據(jù)觀測(cè)、屬性和方法的運(yùn)算逐沙、 watch/event 事件回調(diào)哲思。無(wú) $el .

3. beforeMount:在掛載之前調(diào)用,相關(guān) render 函數(shù)首次被調(diào)用

4. mounted:了被新創(chuàng)建的vm.$el替換吩案,并掛載到實(shí)例上去之后調(diào)用改鉤子棚赔。

5. beforeUpdate:數(shù)據(jù)更新前調(diào)用,發(fā)生在虛擬DOM重新渲染和打補(bǔ)丁徘郭,在這之后會(huì)調(diào)用改鉤子靠益。

6. updated:由于數(shù)據(jù)更改導(dǎo)致的虛擬DOM重新渲染和打補(bǔ)丁,在這之后會(huì)調(diào)用改鉤子残揉。

7. beforeDestroy:實(shí)例銷毀前調(diào)用胧后,實(shí)例仍然可用。

8. destroyed:實(shí)例銷毀之后調(diào)用抱环,調(diào)用后壳快,Vue實(shí)例指示的所有東西都會(huì)解綁纸巷,所有事件監(jiān)聽器和所有子實(shí)例都會(huì)被移除

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

1. created:實(shí)例已經(jīng)創(chuàng)建完成眶痰,因?yàn)樗亲钤缬|發(fā)的瘤旨,所以可以進(jìn)行一些數(shù)據(jù)、資源的請(qǐng)求竖伯。

2. mounted:實(shí)例已經(jīng)掛載完成存哲,可以進(jìn)行一些DOM操作。

3. beforeUpdate:可以在這個(gè)鉤子中進(jìn)一步的更改狀態(tài)七婴,不會(huì)觸發(fā)重渲染宏胯。

4. updated:可以執(zhí)行依賴于DOM的操作,但是要避免更改狀態(tài)本姥,可能會(huì)導(dǎo)致更新無(wú)線循環(huán)。

5. 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 歹鱼。

31.Vue的生命周期

父子間通信:

1. 父親提供數(shù)據(jù)通過(guò)屬性 props傳給兒子泣栈;兒子通過(guò) $on 綁父親的事件,再通過(guò) $emit 觸發(fā)自己的事件(發(fā)布訂閱)

2. 利用父子關(guān)系 $parent 弥姻、 $children 南片,

獲取父子組件實(shí)例的方法:

1. 父組件提供數(shù)據(jù),子組件注入庭敦。 provide 疼进、 inject ,插件用得多螺捐。

2. ref 獲取組件實(shí)例颠悬,調(diào)用組件的屬性矮燎、方法

3. 跨組件通信 Event Bus? (Vue.prototype.bus=newVue)其實(shí)基于bus = new Vue)其實(shí)基于bus=newVue)其實(shí)基于on與$emit

4. vuex? 狀態(tài)管理實(shí)現(xiàn)通信

32.Vuex 工作原理

Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。

狀態(tài)自管理應(yīng)用包含以下幾個(gè)部分:

1. state赔癌,驅(qū)動(dòng)應(yīng)用的數(shù)據(jù)源诞外;

2. view,以聲明方式將 state 映射到視圖灾票;

3. actions峡谊,響應(yīng)在 view 上的用戶輸入導(dǎo)致的狀態(tài)變化。下圖單向數(shù)據(jù)流示意圖:

vuex刊苍,多組件共享狀態(tài)既们,因-單向數(shù)據(jù)流簡(jiǎn)潔性很容易被破壞:

1. 多個(gè)視圖依賴于同一狀態(tài)。

2. 來(lái)自不同視圖的行為需要變更同一狀態(tài)正什。

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

涉及到Vue中的模板編譯原理啥纸,主要過(guò)程:

1. 將模板轉(zhuǎn)換成 ast 樹, ast 用對(duì)象來(lái)描述真實(shí)的JS語(yǔ)法(將真實(shí)DOM轉(zhuǎn)換成虛擬DOM)

2. 優(yōu)化樹

3. 將 ast 樹生成代碼

34.用VNode來(lái)描述一個(gè)DOM結(jié)構(gòu)

虛擬節(jié)點(diǎn)就是用一個(gè)對(duì)象來(lái)描述一個(gè)真實(shí)的DOM元素婴氮。首先將 template (真實(shí)DOM)先轉(zhuǎn)成 ast 斯棒, ast 樹通過(guò) codegen 生成 render 函數(shù), render 函數(shù)里的 _c 方法將它轉(zhuǎn)為虛擬dom

35.diff算法

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

理解:

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

? 1-1. 擴(kuò)展 v-for 為什么要有 key 惠遏,沒(méi)有 key 會(huì)暴力復(fù)用砾跃,舉例子的話隨便說(shuō)一個(gè)比如移動(dòng)節(jié)點(diǎn)或者增加節(jié)點(diǎn)(修改DOM),加 key 只會(huì)移動(dòng)減少操作DOM节吮。

2. 只有是同一個(gè)虛擬節(jié)點(diǎn)才會(huì)進(jìn)行精細(xì)化比較蜓席,否則就是暴力刪除舊的,插入新的课锌。

3. 只進(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)到舊前之前)

36.Computed watch 和 method

computed:默認(rèn)computed也是一個(gè)watcher具備緩存委粉,只有當(dāng)依賴的數(shù)據(jù)變化時(shí)才會(huì)計(jì)算, 當(dāng)數(shù)據(jù)沒(méi)有變化時(shí), 它會(huì)讀取緩存數(shù)據(jù)。如果一個(gè)數(shù)據(jù)依賴于其他數(shù)據(jù)娶桦,使用 computed

watch:每次都需要執(zhí)行函數(shù)贾节。? watch 更適用于數(shù)據(jù)變化時(shí)的異步操作。如果需要在某個(gè)數(shù)據(jù)變化時(shí)做一些事情衷畦,使用watch栗涂。

method:只要把方法用到模板上了,每次一變化就會(huì)重新渲染視圖,性能開銷大

37.v-if 和 v-show 區(qū)別

v-if 如果條件不成立不會(huì)渲染當(dāng)前指令所在節(jié)點(diǎn)的DOM元素

v-show 只是切換當(dāng)前DOM的顯示與隱藏

38.v-for和v-if為什么不能連用

v-for 會(huì)比 v-if 的優(yōu)先級(jí)更高祈争,連用的話會(huì)把 v-if 的每個(gè)元素都添加一下斤程,造成性能問(wèn)題。

39.v-html 會(huì)導(dǎo)致哪些問(wèn)題(簡(jiǎn)單)

XSS 攻擊

v-html 會(huì)替換標(biāo)簽內(nèi)部的元素

40.描述組件渲染和更新過(guò)程

渲染組件時(shí)菩混,會(huì)通過(guò) vue.extend() 方法構(gòu)建子組件的構(gòu)造函數(shù)暖释,并進(jìn)行實(shí)例化。最終手動(dòng)調(diào)用 $mount() 進(jìn)行掛載墨吓。更新組件時(shí)會(huì)進(jìn)行 patchVnode 流程,核心就是 diff 算法纹磺。

41.組件中的data為什么是函數(shù)

避免組件中的數(shù)據(jù)互相影響帖烘。同一個(gè)組件被復(fù)用多次會(huì)創(chuàng)建多個(gè)實(shí)例,如果 data 是一個(gè)對(duì)象的話橄杨,這些實(shí)例用的是同一個(gè)構(gòu)造函數(shù)秘症。為了保證組件的數(shù)據(jù)獨(dú)立,要求每個(gè)組件都必須通過(guò) data 函數(shù)返回一個(gè)對(duì)象作為組件的狀態(tài)式矫。

42.為什么要使用異步組件乡摹?

1. 節(jié)省打包出的結(jié)果,異步組件分開打包采转,采用jsonp的方式進(jìn)行加載聪廉,有效解決文件過(guò)大的問(wèn)題。

2. 核心就是包組件定義變成一個(gè)函數(shù)故慈,依賴 import() 語(yǔ)法板熊,可以實(shí)現(xiàn)文件的分割加載。

43.action 與 mutation 的區(qū)別

mutation 是同步更新察绷, $watch 嚴(yán)格模式下會(huì)報(bào)錯(cuò)

action 是異步操作干签,可以獲取數(shù)據(jù)后調(diào)用 mutation 提交最終數(shù)據(jù)

44.插槽與作用域插槽的區(qū)別

插槽

1. 創(chuàng)建組件虛擬節(jié)點(diǎn)時(shí),會(huì)將組件兒子的虛擬節(jié)點(diǎn)保存起來(lái)拆撼。當(dāng)初始化組件時(shí)容劳,通過(guò)插槽屬性將兒子進(jìn)行分類 {a:[vnode],b[vnode]}

2. 渲染組件時(shí)會(huì)拿對(duì)應(yīng)的 slot 屬性的節(jié)點(diǎn)進(jìn)行替換操作喘沿。(插槽的作用域?yàn)楦附M件)

作用域插槽

1. 作用域插槽在解析的時(shí)候不會(huì)作為組件的孩子節(jié)點(diǎn)。會(huì)解析成函數(shù)竭贩,當(dāng)子組件渲染時(shí)蚜印,會(huì)調(diào)用此函數(shù)進(jìn)行渲染。

2. 普通插槽渲染的作用域是父組件娶视,作用域插槽的渲染作用域是當(dāng)前子組件

45.vue中相同邏輯如何抽離

其實(shí)就是考察 vue.mixin 用法晒哄,給組件每個(gè)生命周期,函數(shù)都混入一些公共邏輯肪获。

46.vue中相同邏輯如何抽離

keep-alive 可以實(shí)現(xiàn)組件的緩存寝凌,當(dāng)組件切換時(shí)不會(huì)對(duì)當(dāng)前組件進(jìn)行卸載。常用的2個(gè)屬性 include/exclude 孝赫,2個(gè)生命周期 activated 较木, deactivated

47.Vue性能優(yōu)化

編碼優(yōu)化:

1. 事件代理

2. keep-alive

3. 拆分組件

4. key 保證唯一性

5. 路由懶加載、異步組件

6. 防抖節(jié)流

Vue加載性能優(yōu)化

1. 第三方模塊按需導(dǎo)入( babel-plugin-component )

2. 圖片懶加載

用戶體驗(yàn)

1. app-skeleton? 骨架屏

2. shellap p殼

3. pwa

SEO優(yōu)化

1. 預(yù)渲染

48.嵌套路由怎么定義青柄?

49.vue-router有哪幾種導(dǎo)航鉤子伐债?

第一種:是全局導(dǎo)航鉤子:router.beforeEach(to,from,next),作用:跳轉(zhuǎn)前進(jìn)行判斷攔截致开。

第二種:組件內(nèi)的鉤子

第三種:?jiǎn)为?dú)路由獨(dú)享組件

50.scss是什么峰锁?在vue.cli中的安裝使用步驟是?有哪幾大特性双戳?

scss是什么?

css的預(yù)編譯虹蒋。

在vue.cli中的安裝使用步驟是?

第一步:用npm 下三個(gè)loader(sass-loader、css-loader飒货、node-sass)

第二步:在build目錄找到webpack.base.config.js魄衅,在那個(gè)extends屬性中加一個(gè)拓展.scss

第三步:還是在同一個(gè)文件,配置一個(gè)module屬性

第四步:然后在組件的style標(biāo)簽加上lang屬性 塘辅,例如:lang=”scss”

有哪幾大特性晃虫?

1、可以用變量扣墩,例如($變量名稱=值)哲银;

2、可以用混合器呻惕,例如()

3盘榨、可以嵌套

51. 簡(jiǎn)述一下Sass、Less蟆融,且說(shuō)明區(qū)別草巡?

他們是動(dòng)態(tài)的樣式語(yǔ)言,是CSS預(yù)處理器,CSS上的一種抽象層。他們是一種特殊的語(yǔ)法/語(yǔ)言而編譯成CSS山憨。

變量符不一樣查乒,less是@,而Sass是$;

Sass支持條件語(yǔ)句郁竟,可以使用if{}else{},for{}循環(huán)等等玛迄。而Less不支持;

Sass是基于Ruby的,是在服務(wù)端處理的棚亩,而Less是需要引入less.js來(lái)處理Less代碼輸出Css到瀏覽器

52.Vue的雙向數(shù)據(jù)綁定原理是什么蓖议?

概:

vue.js 是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過(guò)Object.defineProperty()來(lái)劫持各個(gè)屬性的setter讥蟆,getter勒虾,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)瘸彤。

詳:

第一步:需要observe的數(shù)據(jù)對(duì)象進(jìn)行遞歸遍歷修然,包括子屬性對(duì)象的屬性,都加上 setter和getter這樣的話质况,給這個(gè)對(duì)象的某個(gè)值賦值愕宋,就會(huì)觸發(fā)setter,那么就能監(jiān)聽到了數(shù)據(jù)變化

第二步:compile解析模板指令结榄,將模板中的變量替換成數(shù)據(jù)中贝,然后初始化渲染頁(yè)面視圖,并將每個(gè)指令對(duì)應(yīng)的節(jié)點(diǎn)綁定更新函數(shù)臼朗,添加監(jiān)聽數(shù)據(jù)的訂閱者邻寿,一旦數(shù)據(jù)有變動(dòng),收到通知依溯,更新視圖

第三步:Watcher訂閱者是Observer和Compile之間通信的橋梁,主要做的事情是:1瘟则、在自身實(shí)例化時(shí)往屬性訂閱器(dep)里面添加自己2黎炉、自身必須有一個(gè)update()方法3、待屬性變動(dòng)dep.notice()通知時(shí)醋拧,能調(diào)用自身的update()方法慷嗜,并觸發(fā)Compile中綁定的回調(diào),則功成身退丹壕。

第四步:MVVM作為數(shù)據(jù)綁定的入口庆械,整合Observer、Compile和Watcher三者菌赖,通過(guò)Observer來(lái)監(jiān)聽自己的model數(shù)據(jù)變化缭乘,通過(guò)Compile來(lái)解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁琉用,達(dá)到數(shù)據(jù)變化 -> 視圖更新堕绩;視圖交互變化(input) -> 數(shù)據(jù)model變更的雙向綁定效果策幼。

53.請(qǐng)說(shuō)下封裝 vue 組件的過(guò)程?

首先奴紧,組件可以提升整個(gè)項(xiàng)目的開發(fā)效率特姐。能夠把頁(yè)面抽象成多個(gè)相對(duì)獨(dú)立的模塊,解決了我們傳統(tǒng)項(xiàng)目開發(fā):效率低黍氮、難維護(hù)唐含、復(fù)用性等問(wèn)題。

然后沫浆,使用Vue.extend方法創(chuàng)建一個(gè)組件捷枯,然后使用Vue.component方法注冊(cè)組件。子組件需要數(shù)據(jù)件缸,可以在props中接受定義铜靶。而子組件修改好數(shù)據(jù)后,想把數(shù)據(jù)傳遞給父組件他炊≌耍可以采用emit方法。

54.聊聊你對(duì)Vue.js的template編譯的理解痊末?

首先蚕苇,通過(guò)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)過(guò)generate(將AST語(yǔ)法樹轉(zhuǎn)化成render funtion字符串的過(guò)程)得到render函數(shù)蹬碧,render的返回值是VNode,VNode是Vue的虛擬DOM節(jié)點(diǎn)炒刁,里面有(標(biāo)簽名恩沽、子節(jié)點(diǎn)、文本等等)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翔始,一起剝皮案震驚了整個(gè)濱河市罗心,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌城瞎,老刑警劉巖渤闷,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異脖镀,居然都是意外死亡飒箭,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)补憾,“玉大人漫萄,你說(shuō)我怎么就攤上這事∮遥” “怎么了腾务?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)削饵。 經(jīng)常有香客問(wèn)我岩瘦,道長(zhǎng),這世上最難降的妖魔是什么窿撬? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任启昧,我火速辦了婚禮,結(jié)果婚禮上劈伴,老公的妹妹穿的比我還像新娘密末。我一直安慰自己,他們只是感情好跛璧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布严里。 她就那樣靜靜地躺著,像睡著了一般追城。 火紅的嫁衣襯著肌膚如雪刹碾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天座柱,我揣著相機(jī)與錄音迷帜,去河邊找鬼。 笑死色洞,一個(gè)胖子當(dāng)著我的面吹牛戏锹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播火诸,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼锦针,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了惭蹂?” 一聲冷哼從身側(cè)響起伞插,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤割粮,失蹤者是張志新(化名)和其女友劉穎盾碗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舀瓢,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡廷雅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片航缀。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡商架,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芥玉,到底是詐尸還是另有隱情蛇摸,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布灿巧,位于F島的核電站赶袄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏抠藕。R本人自食惡果不足惜饿肺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盾似。 院中可真熱鬧敬辣,春花似錦、人聲如沸零院。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)门粪。三九已至喊积,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間玄妈,已是汗流浹背乾吻。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拟蜻,地道東北人绎签。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像酝锅,于是被迫代替她去往敵國(guó)和親诡必。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

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