天天看點

vue3 高階 API 大彙總,強到離譜

高階函數是什麼呢?

高階函數英文名叫: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中使用相對少。使用時注意事項:

  1. 使用 mixin 對象時,元件内部和 mixin 包含相同選項,該選項會進行合并處理,并不會覆寫。
  2. 使用的 mixin 對象選項 和執行個體中的選項擁有相同的屬性時,會選擇就近原則,優先繼承執行個體内的值,是以 mixin 對象的屬性會被執行個體中的屬性給覆寫掉。
  3. 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
}      
  1. attrs 是一個非響應式的對象,主要接收 no-props 屬性,經常用來傳遞一些樣式屬性。
  2. slots 是一個 proxy 對象,其中 slots.default() 擷取到的是一個數組,數組長度由元件的插槽決定,數組内是插槽内容。
  3. setup 内不存在this,是以 emit 用來替換 之前 this.$emit 的,用于子傳父時,自定義事件觸發。

十一、watch 新用法

監聽資料變化,做出相應的業務處理。在組合式api中,偵聽器可以監聽一個或多個屬性,也可以是基礎類型資料或引用資料類型。

watch 的特點:

  1. 有惰性:運作的時候,不會立即執行。
  2. 更加具體:需要添加監聽的屬性。
  3. 可以通路屬性之前的值:回調函數内會傳回最新值和修改之前的值。
  4. 可配置:可以添加配置項。

配置項

  • immediate:配置watch屬性是否立即執行,值為 true 時,一旦運作就會立即執行,值為false時,保持惰性。
  • deep:配置 watch 是否深度監聽,值為 true 時,可以監聽對象所有屬性,值為 false 時保持更加具體特性,必須指定到具體的屬性上。

十二、watchEffect

是一個幀聽器,也是一個副作用函數。它會監聽引用資料類型的所有屬性,不需要具體到某個屬性,一旦運作就會立即監聽,元件解除安裝的時候會停止監聽。

watchEffect 特點:

  1. 非惰性:一旦運作就會立即執行。
  2. 更加抽象:使用時不需要具體指定監聽的誰,回調函數内直接使用就可以。相比watch比較難了解。
  3. 不可通路之前的值:隻能通路目前最新的值,通路不到修改之前的值。

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(()=>{
  ....
 })
}      

其他的鈎子函數與上相同。

vue3 高階 API 大彙總,強到離譜

十六、擷取真實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學習筆記系列文章,各個知識點内容介紹的特别詳細。