Vue 知識(shí)點(diǎn)
原理篇
一、Vue 響應(yīng)式原理
- Vue2 中急前,是通過(guò) ES5 中的
defineProperty
api 來(lái)對(duì)對(duì)象的屬性進(jìn)行 get 和 set 操作的攔截,在進(jìn)行攔截操作時(shí)還創(chuàng)建了一個(gè) watcher 用來(lái)跟蹤對(duì)應(yīng)的 value 的變化,因?yàn)檫@種方式無(wú)法對(duì)數(shù)組進(jìn)行攔截钓猬,所以在 vue 中,要實(shí)現(xiàn)數(shù)組的響應(yīng)式碴倾,需要調(diào)用其內(nèi)置的set 的用法)逗噩,defineProperty 是一個(gè)無(wú)法 polyfill 的api,所以 vue 不支持 IE8 以下的版本
- Vue3 使用ES6 的
Proxy
內(nèi)置對(duì)象完全改了響應(yīng)式的底層實(shí)現(xiàn)跌榔,但原理都是類(lèi)似地异雁,(為對(duì)象屬性添加攔截器和偵聽(tīng)器),Proxy 能更高效地對(duì)對(duì)象添加自定義操作僧须,同時(shí)也支持了對(duì)數(shù)組的代理纲刀。不過(guò)也有問(wèn)題,就是 Proxy 不支持對(duì)原始類(lèi)型數(shù)據(jù)的代理担平,所以在 vue3 中示绊,為實(shí)現(xiàn)原始類(lèi)型數(shù)據(jù)的響應(yīng),對(duì)原始數(shù)據(jù)類(lèi)型進(jìn)行了對(duì)象化包裝暂论。同樣地面褐,Proxy 也是一個(gè)無(wú)法被 polyfill 的 api,所以 vue3 不支持 IE11 以下的版本
二取胎、v-model
的實(shí)現(xiàn)原理
v-model 是通過(guò)表單元素的 change/input
事件展哭,然后在事件觸發(fā)時(shí),發(fā)送一個(gè) 自定義的 update 事件闻蛀,并將原始事件對(duì)象中的 value 當(dāng)作參數(shù)發(fā)送出去匪傍,然后更新到 v-model
綁定的值上
應(yīng)用(APP)篇
三、組件的生命周期
Vue 2
beforeCreated => created => beforeMount => mounted => beforeDestroy => destroyed
如果組件發(fā)生了更新觉痛,還會(huì)觸發(fā)以下生命周期鉤子
beforeUpdate => updated
如果使用了 keep-alive
役衡,則會(huì)額外增加兩個(gè)生命周期: actived, deactived
Vue 3
Vue 3 新增了組合式 API,不過(guò) Vue 2 中的 Option API 也可以繼續(xù)使用薪棒,要使用組合式 API手蝎,需要使用 setup
方法或者 <script setup>
語(yǔ)法糖
在組合式 API 中,beforeCreated 和 created 直接整合到了 setup 方法盗尸,其他的采用了 on + 生命周期名稱(chēng)形式的方法鉤子函數(shù)柑船,其中 destroy相關(guān)的鉤子都改成了 unmounted / beforeUnmount
選項(xiàng)式 API 生命周期
Vue2.x | Vue3.x | Composition API |
---|---|---|
beforeCreate | -- (代表無(wú)變化) | setup |
created | -- | setup |
beforeMount | -- | onBeforeMount |
mounted | -- | onMounted |
beforeDestroy | beforeUnmount | onBeforeUnmount |
destroyed | unmounted | onMounted |
同樣的,beforeUpdate 在 composition API 中需要使用 onBeforeUpdate, updated => onUpdated
, activated => onActivated
四泼各、組件間的通信
父子級(jí)組件
當(dāng)子組件需要接收父組件中的數(shù)據(jù)時(shí)鞍时,可以通過(guò) props 的方式傳遞
當(dāng)父組件需要獲取子組件中的數(shù)據(jù)時(shí),可以在子組件中發(fā)送一個(gè)自定義事件,然后將相關(guān)數(shù)據(jù)當(dāng)作參數(shù)傳遞出去逆巍,在父組件中監(jiān)聽(tīng)對(duì)應(yīng)的事件并接收參數(shù)及塘。另外一種方式就是給子組件添加一個(gè) ref,然后在父組件中通過(guò) this.$refs.[componentRefName]
的方式獲取子組件的實(shí)例然后拿到子組件中的數(shù)據(jù)
同級(jí)組件
同級(jí)組件之間進(jìn)行數(shù)據(jù)通信锐极,通丑狭牛可以使用以下幾種方式:
- 將數(shù)據(jù)交給共同的父級(jí)組件管理,子組件通過(guò)自定義事件將父組件傳遞數(shù)據(jù)灵再,而父組件通過(guò) props 將數(shù)據(jù)傳給子組件肋层,這種方式相對(duì)來(lái)說(shuō)比較麻煩,有時(shí)可能需要層層上傳翎迁,甚至到根組件
- 在 Vue 2 中可以通過(guò) new 一個(gè) Vue 的實(shí)例來(lái)創(chuàng)建 eventBus栋猖,通過(guò)全局事件總線(xiàn)來(lái)傳遞數(shù)據(jù),不過(guò)這種方式在 vue 3 中被廢棄了
- 通過(guò)第三方 PubSub 工具(比如:emitter)創(chuàng)建自定義事件汪榔,通過(guò)事件參數(shù)的方式來(lái)實(shí)現(xiàn)同級(jí)組件之間的通信
- 使用 Vuex / redux 這種全局狀態(tài)管理工具也可以實(shí)現(xiàn)組件間的數(shù)據(jù)通信
- 還有種方式就是通過(guò) mixin蒲拉,但這種方式容易導(dǎo)致數(shù)據(jù)被污染,一般不建議使用
深層嵌套組件
父子級(jí)組件進(jìn)行數(shù)據(jù)傳遞痴腌,通過(guò) props 就可以實(shí)現(xiàn)雌团,也比較方便,但當(dāng)一個(gè)組件需要向?qū)O子級(jí)組件或者更深層次的組件傳遞數(shù)據(jù)時(shí)士聪,props 就顯得比較復(fù)雜了锦援,每個(gè)子組件上都需要添加一個(gè) props,這種方法十分不方便剥悟,所以 Vue 提供了 Provider/Inject
來(lái)實(shí)現(xiàn)多級(jí)嵌套組件之間的數(shù)據(jù)傳遞雨涛。
在頂層組件中使用 Provider 定義需要傳遞下去的數(shù)據(jù),在嵌套層級(jí)組件中通過(guò) Inject 來(lái)使用
需要注意的是懦胞,組件 Provider 中的數(shù)據(jù),只提供給其子孫級(jí)組件使用
五凉泄、對(duì) Vue 進(jìn)行擴(kuò)展
在 vue 2 中躏尉,可以通過(guò)給 Vue 的原型加上自定義的方法來(lái)實(shí)現(xiàn)全局的方法,在組件實(shí)例中通過(guò) this.customMethod 調(diào)用
Vue.prototype.customMethod
Vue 3 廢棄了修改 prototype 來(lái)對(duì) vue 進(jìn)行自定義擴(kuò)展的操作后众。vue 3 為應(yīng)用實(shí)例(通常命名為 app)添加了 config 對(duì)象屬性胀糜,在 config 屬性上,通過(guò)配置 globalProperties 來(lái)實(shí)現(xiàn)自定義擴(kuò)展蒂誉,調(diào)用的方法與 vue 2 中基本一致
六教藻、API 篇
-
v-if
與v-show
的異同v-if 與 v-show 都是控制元素的顯示與隱藏,其中 v-if 是通過(guò)控制 DOM 節(jié)點(diǎn)的創(chuàng)建與銷(xiāo)毀來(lái)實(shí)現(xiàn)的右锨,v-show 是通過(guò)控制 css 中的 display 屬性來(lái)實(shí)現(xiàn)的括堤。
v-if 有更高的渲染開(kāi)銷(xiāo),v-show 有更高的初始化開(kāi)銷(xiāo),如果要頻繁控制 DOM 節(jié)點(diǎn)的話(huà)悄窃,需要使用 v-show讥电,如果用在組件上,需要能觸發(fā)組件的生命周期轧抗,則需要使用 v-if恩敌,這時(shí)需要注意最好不要對(duì)組件進(jìn)行頻繁的顯示與隱藏切換操作
另外,v-if 可以與 v-else-if, v-else 配合使用來(lái)進(jìn)行條件渲染横媚,不過(guò)綁定了這些指令的元素必須為同級(jí)的
-
v-if
與v-for
v-if 與 v-for 其實(shí)是可以在同一個(gè)元素上使用的纠炮,但是不管是官方還是實(shí)際項(xiàng)目中都不推薦這么使用,如果需要在 v-for 生成的列表元素使用條件渲染灯蝴,建議將 v-for 放在一個(gè) template 標(biāo)簽上去使用恢口,同理,也是建議將 v-if 放在 template 上去使用绽乔,也可以自定義一個(gè)包裹容器弧蝇,只是 template 不會(huì)生成額外的 DOM 節(jié)點(diǎn)。
優(yōu)先級(jí):在 vue 2.x 中折砸,v-for 的優(yōu)先級(jí)要比 v-if 高看疗,但在 vue 3中,v-if 的優(yōu)先級(jí)要比 v-for 高
-
key
的作用在 vue 中睦授,key 這個(gè)屬性最常見(jiàn)的用法就是與 v-for 一起使用两芳,當(dāng)然也可以獨(dú)立使用,key 的主要作用就是對(duì)組件或虛擬DOM節(jié)點(diǎn)添加唯一標(biāo)識(shí)符去枷,方便底層 diff 算法在節(jié)點(diǎn)或組件發(fā)生變化時(shí)能快速定位更新怖辆。如果不使用 key,Vue 會(huì)使用一種最大限度減少動(dòng)態(tài)元素并且盡可能的嘗試就地修改/復(fù)用相同類(lèi)型元素的算法删顶。某些時(shí)候會(huì)導(dǎo)致 BUG竖螃,比如 v-for 渲染了 輸入類(lèi)元素時(shí),缺少 key 或使用 index 當(dāng)作key時(shí)逗余,當(dāng)列表長(zhǎng)度發(fā)生了非順序性變化時(shí)特咆,就極易出 BUG。
-
watch
與computed
watch 與 computed 在很多時(shí)候录粱,用法都差不多腻格,但也有差異,computed 主要是依賴(lài)項(xiàng)發(fā)生了變化時(shí)啥繁,它自身屬性跟著變化菜职,但如果其依賴(lài)項(xiàng)沒(méi)有發(fā)生變化時(shí),則其同樣不會(huì)發(fā)生變化旗闽,這種特性使其可以用來(lái)進(jìn)行一定的性能優(yōu)化酬核。watch 主要是當(dāng)偵聽(tīng)的數(shù)據(jù)發(fā)生變化時(shí)蜜另,去觸發(fā)其他的數(shù)據(jù)變化。
簡(jiǎn)單來(lái)說(shuō)愁茁,watch 主要用于需要根據(jù)數(shù)據(jù)變化來(lái)修改其他數(shù)據(jù)的操作蚕钦,而computed更適用于依賴(lài)其他數(shù)據(jù)變化來(lái)修改自身的操作
另外,有較大開(kāi)銷(xiāo)和異步操作時(shí)鹅很,watch 更合適
-
樣式綁定
Class綁定:vue 可以對(duì)元素的類(lèi)名進(jìn)行動(dòng)態(tài)綁定嘶居,其值大概有以下幾種:
-
{ className: truthy | falsy }
: 當(dāng)綁定的值為對(duì)象時(shí),該對(duì)象的屬性則會(huì)被編譯成元素的類(lèi)目促煮,而屬性對(duì)應(yīng)的值應(yīng)該為一個(gè)Boolean值邮屁,用于控制該屬性是否被編譯成類(lèi)目 -
classNameString[]
: 純 className 字符串組成的數(shù)組,數(shù)組中的所以元素都會(huì)被編譯成樣式類(lèi)別 -
classNameString | classObject []
: 對(duì)象語(yǔ)法與數(shù)組語(yǔ)法混用的模式
Style 綁定:
-
{ styleProperty: styleValue }
: 當(dāng)樣式綁定的值為對(duì)象時(shí)菠齿,對(duì)象的property則應(yīng)該為具體樣式對(duì)應(yīng)的屬性佑吝,value 則為樣式的值,注意寫(xiě)法需要符合js對(duì)象的基本語(yǔ)法 -
styleObj[]
: 當(dāng)綁定的值為數(shù)組時(shí)绳匀,則數(shù)組中的每個(gè)元素應(yīng)該為一個(gè)樣式對(duì)象的引用
-
-
組件
props
與data
的優(yōu)先級(jí)根據(jù) vue 的源碼芋忿,props 的優(yōu)先級(jí)要高于 data,也就是說(shuō)當(dāng) props 和 data 中有同名屬性時(shí)疾棵,最終會(huì)渲染 data 中的而不是 props 中的那個(gè)
異步組件:在組件的 components 中戈钢,通過(guò)
() => import(Component)
導(dǎo)入的組件就是異步組件動(dòng)態(tài)組件:需要配合 keep-alive 使用,通過(guò)給組件添加
:is
屬性來(lái)指定
七是尔、其他需要熟悉用法的功能
- 自定義指令
- 插槽與作用域插槽
- 渲染函數(shù)(比較高級(jí)的用法殉了,包括在 Vue 中寫(xiě) JSX)
- 過(guò)濾器(Vue 3 廢棄了,vue2中用的也不算多)
八拟枚、$nextTick
簡(jiǎn)單的來(lái)說(shuō)薪铜,nextTick 的工作原理就是將傳入的回調(diào)收集起來(lái),等到 DOM 加載完成或者watcher觸發(fā)之后再調(diào)用恩溅。因?yàn)槭怯玫囊蕾?lài)收集的機(jī)制隔箍,所以先被收集的會(huì)先執(zhí)行,所以如果多個(gè) nextTick 嵌套時(shí)脚乡,外層的nextTick 會(huì)先執(zhí)行
Vue 3 新增的一些值得關(guān)注的特性
- Composition API (重點(diǎn))
- setup 方法
-
<script setup>
語(yǔ)法糖 - 在 Composition API 中慎用解構(gòu)賦值(可能導(dǎo)致響應(yīng)性丟失)鞍恢,或者需要配合 toRefs 使用
- Teleport內(nèi)置組件 (了解用法)
- 在
<style>
標(biāo)簽中使用 JS 變量 - 深度選擇器的變更
- 樣式的插槽選擇器與全局選擇器