高階函數是什么呢?
高階函數英文名叫: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 的時候去獲取內容就可以了。
原文鏈接:https://www.toutiao.com/a7032075595513217572/