Vue3 高階 API 大匯總,強(qiáng)到離譜
高階函數(shù)是什么呢?
高階函數(shù)英文名叫:Higher Order function ,一個(gè)函數(shù)可以接收一個(gè)或多個(gè)函數(shù)作為輸入,或者輸出一個(gè)函數(shù),至少滿足上述條件之一的函數(shù),叫做高階函數(shù)。
前言
本篇內(nèi)容的知識(shí)點(diǎn)比較多,講得不夠細(xì)致,不熟悉的可翻閱前幾篇文章,分別對(duì)每個(gè)知識(shí)點(diǎn)都有一篇特別詳細(xì)的文章。建議讀者收藏!
一、Mixin 混入
mixin 混入,提供了一種非常靈活的方式,來(lái)分發(fā) vue 組件中的可復(fù)用功能,一個(gè)mixin 對(duì)象可以包含任意組件選項(xiàng),當(dāng)組件使用 mixin 對(duì)象時(shí),所有的 mixin 對(duì)象的選項(xiàng)將被混入組件本身的選項(xiàng)。
mixins 是一個(gè)數(shù)組,一個(gè)組件可以引入多個(gè) mixin 對(duì)象。使用方法如:
- <script>
- const myMixin = {
- data(){
- return {
- num:520
- }
- },
- mounted(){
- console.log('mixin mounted');
- }
- }
- export default {
- mixins:[myMixin],
- }
- </script>
mixin 使用主要針對(duì)選項(xiàng)式API,在vue3中使用相對(duì)少。使用時(shí)注意事項(xiàng):
- 使用 mixin 對(duì)象時(shí),組件內(nèi)部和 mixin 包含相同選項(xiàng),該選項(xiàng)會(huì)進(jìn)行合并處理,并不會(huì)覆蓋。
- 使用的 mixin 對(duì)象選項(xiàng) 和實(shí)例中的選項(xiàng)擁有相同的屬性時(shí),會(huì)選擇就近原則,優(yōu)先繼承實(shí)例內(nèi)的值,所以 mixin 對(duì)象的屬性會(huì)被實(shí)例中的屬性給覆蓋掉。
- mixin 對(duì)象也可以添加生命周期鉤子函數(shù),兩者都會(huì)執(zhí)行,優(yōu)先執(zhí)行 mixin 中的, 然后再執(zhí)行實(shí)例中的。
mixin也可以自定義屬性,如果與實(shí)例中的屬性沖突時(shí),可以使用 optionMergeStrategies 選項(xiàng)合并策略,自定義合并規(guī)則。
二、自定義指令
自定義指令分為全局和局部自定義指令。
2.1、自定義指令定義
全局自定義指令
在 vue3 中,vue 實(shí)例通過(guò)createApp 創(chuàng)建,所以全局自定義指令的掛載方式也改變了, directive 被掛載到 app上。
- app.directive('focus',{
- mounted(el){
- el.focus()
- }
- })
局部自定義指令
- const autoFocus = {
- focus:{
- mounted(el){
- el.focus()
- }
- }
- }
- export default{
- directives:autoFocus,
- }
自定義指令 v-xxx 直接使用就好,對(duì)應(yīng)上述示例自定義指令為 v-focus。
2.2、自定義指令鉤子函數(shù)參數(shù)
每個(gè)鉤子里面的參數(shù)含義:
mounted(el,binding,vnode){…}
el:代表當(dāng)前使用該指令的元素
binding:指令傳來(lái)的值
vnode:當(dāng)前元素節(jié)點(diǎn)相關(guān)
2.3、自定義指令鉤子函數(shù)
一個(gè)指令定義對(duì)象可以提供如下幾個(gè)鉤子函數(shù)(都是可選的,根據(jù)需要引入)
- created :綁定元素屬性或事件監(jiān)聽(tīng)器被應(yīng)用之前調(diào)用。該指令需要附加需要在普通的 v-on 事件監(jiān)聽(tīng)器前調(diào)用的事件監(jiān)聽(tīng)器時(shí),這很有用。
- beforeMounted :當(dāng)指令第一次綁定到元素并且在掛載父組件之前執(zhí)行。
- mounted :綁定元素的父組件被掛載之后調(diào)用。
- beforeUpdate :在更新包含組件的 VNode 之前調(diào)用。
- updated :在包含組件的 VNode 及其子組件的 VNode 更新后調(diào)用。
- beforeUnmounted :在卸載綁定元素的父組件之前調(diào)用
- unmounted :當(dāng)指令與元素解除綁定且父組件已卸載時(shí),只調(diào)用一次。
2.4、自定義指令參數(shù)
自定義指令的也可以帶參數(shù),參數(shù)可以是動(dòng)態(tài)的,參數(shù)可以根據(jù)組件實(shí)例數(shù)據(jù)進(jìn)行實(shí)時(shí)更新。
使用方法如下:
- <template>
- <div>
- <div v-fixed:pos="posData">定位</div>
- </div>
- </template>
- <script>
- //自定義指令動(dòng)態(tài)參數(shù)
- const autoFocus = {
- fixed:{
- beforeMount(el,binding){
- el.style.position = "fixed"
- el.style.left = binding.value.left+'px'
- el.style.top = binding.value.top + 'px'
- }
- }
- }
- export default {
- directives:autoFocus,
- setup(){
- const posData = {
- left:20,
- top:200
- }
- return {
- posData,
- }
- }
- }
- </script>
三、teleport 傳送門(mén)
teleport 傳送門(mén)組件,提供一種簡(jiǎn)潔的方式,可以指定它里面的內(nèi)容的父元素。通俗易懂地講,就是 teleport 中的內(nèi)容允許我們控制在任意的 DOM 中,使用簡(jiǎn)單。
使用語(yǔ)法:
- <teleport to="body">
- <div>
- 需要?jiǎng)?chuàng)建的內(nèi)容
- </div>
- </teleport>
to 屬性是指定 teleport 中的內(nèi)容加入的 DOM 元素。可以是標(biāo)簽名,也可以是 id 或類(lèi)名。
為什么使用 teleport ?
使用 vue 開(kāi)發(fā)時(shí),都是在多個(gè)組件之間不斷地嵌套,處理元素的樣式或者層級(jí)的時(shí)候就會(huì)變得困難。如我們需要添加一個(gè) modal 模態(tài)框或 toast 提示框,如果我們把這樣的框可以從 vue 組件中剝離出來(lái),我們樣式和層級(jí)設(shè)置起來(lái)會(huì)更加簡(jiǎn)便。
有些同學(xué)會(huì)想,這直接放到 index.html 中不就好了嗎?另外 modal 、toast 元素需要使用 vue 組件的狀態(tài)值,通過(guò)狀態(tài)控制 modal、toast 的隱藏顯示。如果直接放入 index.html 則狀態(tài)控制就復(fù)雜了。
所以 teleport 傳送門(mén)組件就派上用場(chǎng)了。有點(diǎn)像“哆啦A夢(mèng)”的任意門(mén),可以把元素傳送到任意的元素內(nèi)。同時(shí)還可以使用 vue 組件內(nèi)的狀態(tài)值控制它。
四、setup
setup 用來(lái)寫(xiě)組合式 api,從生命周期鉤子函數(shù)角度分析,相當(dāng)于取代了 beforeCreate 。會(huì)在 creted 之前執(zhí)行。內(nèi)部的屬性和方法,必須 return 暴露出來(lái),將屬性掛載到實(shí)例上,否則沒(méi)有辦法使用。setup內(nèi)部沒(méi)有 this ,所以不能掛載 this 相關(guān)的東西,它可以接收兩個(gè)參數(shù):props 和 context 。
setup 特性:
1、這個(gè)函數(shù)會(huì)在 created 之前執(zhí)行,上述已解釋。
2、setup 內(nèi)部沒(méi)有 this,不能掛載 this 相關(guān)的東西。
3、setup 內(nèi)部的屬性和方法,必須 return 暴露出來(lái),否則沒(méi)有辦法使用。
4、setup 內(nèi)部數(shù)據(jù)不是響應(yīng)式的。
5、setup不能調(diào)用生命周期相關(guān)函數(shù),但生命周期函數(shù)可以調(diào)用setup內(nèi)的函數(shù)。
五、ref
ref 主要作用是使基礎(chǔ)類(lèi)的數(shù)據(jù)具備響應(yīng)式能力,使用之前必須引入。在 Composition API中數(shù)據(jù)不具備響應(yīng)式,修改數(shù)據(jù)時(shí)視圖不會(huì)改變,所以在創(chuàng)建數(shù)據(jù)時(shí),使用ref包裹一下,讓數(shù)據(jù)具備響應(yīng)式。
ref 使用:
- import { ref } from "vue"
- export default{
- setup(){
- let mood = ref("此時(shí)心情好差呀!")
- setTimeout(()=>{
- mood.value = "心情要變的像人一樣美"
- },3000)
- return{
- mood
- }
- }
- }
六、reactive
讓引用類(lèi)型的數(shù)據(jù)具備響應(yīng)式。
與上述的 ref 原理和用法都一致。
- import { reactive } from "vue"
- let me = reactive({
- single:true,
- want:"暖的像火爐的暖男"
- })
七、readonly
讓數(shù)據(jù)只讀,不能修改數(shù)據(jù)。
父子組件之間傳值時(shí),Vue 是單向數(shù)據(jù)流,為了防止子組件修改數(shù)據(jù),所以使用 readonly 包裹數(shù)據(jù),保證只能在源數(shù)據(jù)上修改。
- import { readonly } from "vue"
- let me = readonly({
- single:true,
- want:"要一個(gè)對(duì)象"
- })
八、toRefs
toRefs 用來(lái)解構(gòu) ref、reactive 包裹的響應(yīng)式數(shù)據(jù)。
使用:
- import { ref , reactive, toRefs } from "vue"
- let me = reactive({
- single:true,
- want:"暖的像火爐的暖男"
- })
- const { single, want } = toRefs( me )
九、toRef
父子組件之間進(jìn)行傳值時(shí),有些參數(shù)是可選參數(shù),toRefs 解構(gòu)參數(shù)不存在時(shí)就會(huì)報(bào)錯(cuò),使用 toRef 解決該問(wèn)題。
使用:
- import { toRef } from "vue"
- const love = toRef(obj,'love')
解構(gòu)時(shí)先檢查 obj 對(duì)象是否存在 love 屬性,如果存在就繼承obj對(duì)象中的屬性值,如果不存在就會(huì)創(chuàng)建一個(gè)。
十、context
setup(props,context)。
context 上下文環(huán)境,其中包括了屬性、插槽、自定義事件三部分。
- setup(props,context){
- const { attrs,slots,emit } = context
- }
attrs 是一個(gè)非響應(yīng)式的對(duì)象,主要接收 no-props 屬性,經(jīng)常用來(lái)傳遞一些樣式屬性。
slots 是一個(gè) proxy 對(duì)象,其中 slots.default() 獲取到的是一個(gè)數(shù)組,數(shù)組長(zhǎng)度由組件的插槽決定,數(shù)組內(nèi)是插槽內(nèi)容。
setup 內(nèi)不存在this,所以 emit 用來(lái)替換 之前 this.$emit 的,用于子傳父時(shí),自定義事件觸發(fā)。
十一、watch 新用法
監(jiān)聽(tīng)數(shù)據(jù)變化,做出相應(yīng)的業(yè)務(wù)處理。在組合式api中,偵聽(tīng)器可以監(jiān)聽(tīng)一個(gè)或多個(gè)屬性,也可以是基礎(chǔ)類(lèi)型數(shù)據(jù)或引用數(shù)據(jù)類(lèi)型。
watch 的特點(diǎn):
- 有惰性:運(yùn)行的時(shí)候,不會(huì)立即執(zhí)行。
- 更加具體:需要添加監(jiān)聽(tīng)的屬性。
- 可以訪問(wèn)屬性之前的值:回調(diào)函數(shù)內(nèi)會(huì)返回最新值和修改之前的值。
- 可配置:可以添加配置項(xiàng)。
配置項(xiàng)
- immediate:配置watch屬性是否立即執(zhí)行,值為 true 時(shí),一旦運(yùn)行就會(huì)立即執(zhí)行,值為false時(shí),保持惰性。
- deep:配置 watch 是否深度監(jiān)聽(tīng),值為 true 時(shí),可以監(jiān)聽(tīng)對(duì)象所有屬性,值為 false 時(shí)保持更加具體特性,必須指定到具體的屬性上。
十二、watchEffect
是一個(gè)幀聽(tīng)器,也是一個(gè)副作用函數(shù)。它會(huì)監(jiān)聽(tīng)引用數(shù)據(jù)類(lèi)型的所有屬性,不需要具體到某個(gè)屬性,一旦運(yùn)行就會(huì)立即監(jiān)聽(tīng),組件卸載的時(shí)候會(huì)停止監(jiān)聽(tīng)。
watchEffect 特點(diǎn):
- 非惰性:一旦運(yùn)行就會(huì)立即執(zhí)行。
- 更加抽象:使用時(shí)不需要具體指定監(jiān)聽(tīng)的誰(shuí),回調(diào)函數(shù)內(nèi)直接使用就可以。相比watch比較難理解。
- 不可訪問(wèn)之前的值:只能訪問(wèn)當(dāng)前最新的值,訪問(wèn)不到修改之前的值。
watch 的前兩個(gè)特點(diǎn)與 watchEffect 的兩個(gè)特點(diǎn)剛好相反,watch 通過(guò)配置項(xiàng)可以修改成帶有 watchEffect 特點(diǎn)
十三、computed 新用法
在組合式api中計(jì)算屬性用法也發(fā)生了改變,使用之前需要引入。
- import { ref, computed } from "vue"
- export default{
- setup(){
- let sum = computed(()=>{
- return ....
- })
- }
- }
也可以是選項(xiàng)式寫(xiě)法:
- let sum = computed({
- get:()=>{
- return ....
- },
- set:(value)=>{
- return ....
- }
- })
十四、provide / inject
provide發(fā)射數(shù)據(jù)或函數(shù),inject 接收數(shù)據(jù)或函數(shù)。
project / inject 類(lèi)似與發(fā)布訂閱,主要用在組件傳值層級(jí)太深,或兄弟組件沒(méi)法傳參,此時(shí)使用 project / inject 特別方便。
- //發(fā)射
- import { provide, readonly } from "vue"
- provide('info',readonly(info))
- //接收
- import { inject } from "vue"
- const info = inject('info')
十五、生命周期鉤子函數(shù)新寫(xiě)法
組合式api中,setup代替了beforeCreated和created,所以這兩個(gè)鉤子失效,其他的只需要引入時(shí)前面加on即可。
- import { onBeforeMount } from "vue"
- setup(){
- onBeforeMount(()=>{
- ....
- })
- }
其他的鉤子函數(shù)與上相同。

十六、獲取真實(shí)DOM
此處的 ref 與上邊的 ref 不同,是獲取真實(shí)DOM節(jié)點(diǎn)的函數(shù)。
使用時(shí):
- <div ref="box" class="test" id="boxtest">獲取真實(shí)DOM</div>
- import { ref,onMounted } from "vue"
- export default {
- setup(){
- const box = ref(null)
- onMounted(()=>{
- console.log('box',box.value);
- })
- return {
- box
- }
- }
- }
使用的時(shí)候記得在return,然后再 mounted 的時(shí)候去獲取內(nèi)容就可以了。