高階函式是什麼呢?
高階函式英文名叫:Higher Order function ,一個函式可以接收一個或多個函式作為輸入,或者輸出一個函式,至少滿足上述條件之一的函式,叫做高階函式。
前言
本篇內容的知識點比較多,講得不夠細緻,不熟悉的可翻閱前幾篇文章,分別對每個知識點都有一篇特別詳細的文章。建議讀者收藏!
一、Mixin 混入
mixin 混入,提供了一種非常靈活的方式,來分發 vue 元件中的可複用功能,一個mixin 物件可以包含任意元件選項,當元件使用 mixin 物件時,所有的 mixin 物件的選項將被混入元件本身的選項。
mixins 是一個陣列,一個元件可以引入多個 mixin 物件。使用方法如:
<script> const myMixin = { data(){ return { num:520 } }, mounted(){ console.log('mixin mounted'); } } export default { mixins:[myMixin], } </script>
mixin 使用主要針對選項式API,在vue3中使用相對少。使用時注意事項:
- 使用 mixin 物件時,元件內部和 mixin 包含相同選項,該選項會進行合併處理,並不會覆蓋。
- 使用的 mixin 物件選項 和例項中的選項擁有相同的屬性時,會選擇就近原則,優先繼承例項內的值,所以 mixin 物件的屬性會被例項中的屬性給覆蓋掉。
- mixin 物件也可以新增生命週期鉤子函式,兩者都會執行,優先執行 mixin 中的, 然後再執行例項中的。
mixin也可以自定義屬性,如果與例項中的屬性衝突時,可以使用 optionMergeStrategies 選項合併策略,自定義合併規則。
二、自定義指令
自定義指令分為全域性和區域性自定義指令。
2.1、自定義指令定義
全域性自定義指令
在 vue3 中,vue 例項通過createApp 建立,所以全域性自定義指令的掛載方式也改變了, directive 被掛載到 app上。
app.directive('focus',{
mounted(el){
el.focus()
}
})
區域性自定義指令
const autoFocus = { focus:{ mounted(el){ el.focus() } } } export default{ directives:autoFocus, }
自定義指令 v-xxx 直接使用就好,對應上述示例自定義指令為 v-focus。
2.2、自定義指令鉤子函式引數
每個鉤子裡面的引數含義:
mounted(el,binding,vnode){…}
el:代表當前使用該指令的元素
binding:指令傳來的值
vnode:當前元素節點相關
2.3、自定義指令鉤子函式
一個指令定義物件可以提供如下幾個鉤子函式(都是可選的,根據需要引入)
- created :繫結元素屬性或事件監聽器被應用之前呼叫。該指令需要附加需要在普通的 v-on 事件監聽器前呼叫的事件監聽器時,這很有用。
- beforeMounted :當指令第一次繫結到元素並且在掛載父元件之前執行。
- mounted :繫結元素的父元件被掛載之後呼叫。
- beforeUpdate :在更新包含元件的 VNode 之前呼叫。
- updated :在包含元件的 VNode 及其子元件的 VNode 更新後呼叫。
- beforeUnmounted :在解除安裝繫結元素的父元件之前呼叫
- unmounted :當指令與元素解除繫結且父元件已解除安裝時,只呼叫一次。
2.4、自定義指令引數
自定義指令的也可以帶引數,引數可以是動態的,引數可以根據元件例項資料進行實時更新。
使用方法如下:
<template> <div> <div v-fixed:pos="posData">定位</div> </div> </template> <script> //自定義指令動態引數 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 傳送門
teleport 傳送門元件,提供一種簡潔的方式,可以指定它裡面的內容的父元素。通俗易懂地講,就是 teleport 中的內容允許我們控制在任意的 DOM 中,使用簡單。
使用語法:
<teleport to="body">
<div>
需要建立的內容
</div>
</teleport>
to 屬性是指定 teleport 中的內容加入的 DOM 元素。可以是標籤名,也可以是 id 或類名。
為什麼使用 teleport ?
使用 vue 開發時,都是在多個元件之間不斷地巢狀,處理元素的樣式或者層級的時候就會變得困難。如我們需要新增一個 modal 模態框或 toast 提示框,如果我們把這樣的框可以從 vue 元件中剝離出來,我們樣式和層級設定起來會更加簡便。
有些同學會想,這直接放到 index.html 中不就好了嗎?另外 modal 、toast 元素需要使用 vue 元件的狀態值,通過狀態控制 modal、toast 的隱藏顯示。如果直接放入 index.html 則狀態控制就複雜了。
所以 teleport 傳送門元件就派上用場了。有點像“哆啦A夢”的任意門,可以把元素傳送到任意的元素內。同時還可以使用 vue 元件內的狀態值控制它。
四、setup
setup 用來寫組合式 api,從生命週期鉤子函式角度分析,相當於取代了 beforeCreate 。會在 creted 之前執行。內部的屬性和方法,必須 return 暴露出來,將屬性掛載到例項上,否則沒有辦法使用。setup內部沒有 this ,所以不能掛載 this 相關的東西,它可以接收兩個引數:props 和 context 。
setup 特性:
1、這個函式會在 created 之前執行,上述已解釋。
2、setup 內部沒有 this,不能掛載 this 相關的東西。
3、setup 內部的屬性和方法,必須 return 暴露出來,否則沒有辦法使用。
4、setup 內部資料不是響應式的。
5、setup不能呼叫生命週期相關函式,但生命週期函式可以呼叫setup內的函式。
五、ref
ref 主要作用是使基礎類的資料具備響應式能力,使用之前必須引入。在 Composition API中資料不具備響應式,修改資料時檢視不會改變,所以在建立資料時,使用ref包裹一下,讓資料具備響應式。
ref 使用:
import { ref } from "vue" export default{ setup(){ let mood = ref("此時心情好差呀!") setTimeout(()=>{ mood.value = "心情要變的像人一樣美" },3000) return{ mood } } }
六、reactive
讓引用型別的資料具備響應式。
與上述的 ref 原理和用法都一致。
import { reactive } from "vue" let me = reactive({ single:true, want:"暖的像火爐的暖男" })
七、readonly
讓資料只讀,不能修改資料。
父子元件之間傳值時,Vue 是單向資料流,為了防止子元件修改資料,所以使用 readonly 包裹資料,保證只能在源資料上修改。
import { readonly } from "vue" let me = readonly({ single:true, want:"要一個物件" })
八、toRefs
toRefs 用來解構 ref、reactive 包裹的響應式資料。
使用:
import { ref , reactive, toRefs } from "vue" let me = reactive({ single:true, want:"暖的像火爐的暖男" }) const { single, want } = toRefs( me )
九、toRef
父子元件之間進行傳值時,有些引數是可選引數,toRefs 解構引數不存在時就會報錯,使用 toRef 解決該問題。
使用:
import { toRef } from "vue"
const love = toRef(obj,'love')
解構時先檢查 obj 物件是否存在 love 屬性,如果存在就繼承obj物件中的屬性值,如果不存在就會建立一個。
十、context
setup(props,context)。
context 上下文環境,其中包括了屬性、插槽、自定義事件三部分。
setup(props,context){ const { attrs,slots,emit } = context }
- attrs 是一個非響應式的物件,主要接收 no-props 屬性,經常用來傳遞一些樣式屬性。
- slots 是一個 proxy 物件,其中 slots.default() 獲取到的是一個陣列,陣列長度由元件的插槽決定,陣列內是插槽內容。
- setup 內不存在this,所以 emit 用來替換 之前 this.$emit 的,用於子傳父時,自定義事件觸發。
十一、watch 新用法
監聽資料變化,做出相應的業務處理。在組合式api中,偵聽器可以監聽一個或多個屬性,也可以是基礎型別資料或引用資料型別。
watch 的特點:
- 有惰性:執行的時候,不會立即執行。
- 更加具體:需要新增監聽的屬性。
- 可以訪問屬性之前的值:回撥函式內會返回最新值和修改之前的值。
- 可配置:可以新增配置項。
配置項
- immediate:配置watch屬性是否立即執行,值為 true 時,一旦執行就會立即執行,值為false時,保持惰性。
- deep:配置 watch 是否深度監聽,值為 true 時,可以監聽物件所有屬性,值為 false 時保持更加具體特性,必須指定到具體的屬性上。
十二、watchEffect
是一個幀聽器,也是一個副作用函式。它會監聽引用資料型別的所有屬性,不需要具體到某個屬性,一旦執行就會立即監聽,元件解除安裝的時候會停止監聽。
watchEffect 特點:
- 非惰性:一旦執行就會立即執行。
- 更加抽象:使用時不需要具體指定監聽的誰,回撥函式內直接使用就可以。相比watch比較難理解。
- 不可訪問之前的值:只能訪問當前最新的值,訪問不到修改之前的值。
watch 的前兩個特點與 watchEffect 的兩個特點剛好相反,watch 通過配置項可以修改成帶有 watchEffect 特點
十三、computed 新用法
在組合式api中計算屬性用法也發生了改變,使用之前需要引入。
import { ref, computed } from "vue" export default{ setup(){ let sum = computed(()=>{ return .... }) } }
也可以是選項式寫法:
let sum = computed({ get:()=>{ return .... }, set:(value)=>{ return .... } })
十四、provide / inject
provide發射資料或函式,inject 接收資料或函式。
project / inject 類似與釋出訂閱,主要用在元件傳值層級太深,或兄弟元件沒法傳參,此時使用 project / inject 特別方便。
//發射 import { provide, readonly } from "vue" provide('info',readonly(info)) //接收 import { inject } from "vue" const info = inject('info')
十五、生命週期鉤子函式新寫法
組合式api中,setup代替了beforeCreated和created,所以這兩個鉤子失效,其他的只需要引入時前面加on即可。
import { onBeforeMount } from "vue" setup(){ onBeforeMount(()=>{ .... }) }
其他的鉤子函式與上相同。
十六、獲取真實DOM
此處的 ref 與上邊的 ref 不同,是獲取真實DOM節點的函式。
使用時:
<div ref="box" class="test" id="boxtest">獲取真實DOM</div> import { ref,onMounted } from "vue" export default { setup(){ const box = ref(null) onMounted(()=>{ console.log('box',box.value); }) return { box } } }
使用的時候記得在return,然後再 mounted 的時候去獲取內容就可以了。
本篇文章介紹的知識點都很粗略,想要更多學習的小夥伴可以點個關注,檢視前邊的vue3學習筆記系列文章,各個知識點內容介紹的特別詳細。