一文解鎖vue3中hooks的使用姿勢

2023-09-06 06:05:45

vue3 中的 hooks 是什麼?

簡單來說如果你的函數中用到了諸如 ref,reactive,onMounted 等 vue 提供的 api 的話,那麼它就是一個 hooks 函數,如果沒用到它就是一個普通工具函數。至於它為什麼叫 hooks,我的理解則是

它可以通過特定的函數將邏輯 "鉤入" 元件中,使得開發者能夠更靈活地構建和管理元件的功能從而提高程式碼的可讀性以及可維護性等

本篇文章將介紹hooks如何在vue3中使用以及它的一些實際使用例子,讓大家能更好的瞭解和使用hooks

在 vue3 中使用

上面說到 hooks 函數裡包含了 vue 提供的 api,下面我們就簡單的來舉個例子看一下 vue3 中的 hooks 函數。一般來說,如果一個你得函數為 hooks 函數,那麼你需要將其以 use 開頭命名。在 src 下新建一個 hooks 目錄專門存放 hooks 函數,然後寫下第一個非常簡單的 hooks 函數 useAdd

import { ref } from "vue";
export const useAdd = () => {
  const a = ref(1);
  setInterval(() => {
    a.value++;
  }, 1000);
  return a;
};

這是一個非常簡單的 hooks 函數,每隔一秒就讓 a.value 加 1,最後返回一個響應式的 a,我們在元件中參照一下

<template>
  <div>{{ a }}</div>
</template>

<script lang='ts' setup>
import { useAdd } from "../hooks/useAdd"
const a = useAdd()
</script>

此時我們會看到每隔一秒頁面上的值就會加 1,所以說 a 還是保持了它的響應式特性

當然這只是個簡單的例子,後面會詳細介紹一個 hooks 實際應用的場景

mixin 與 hooks

我們都知道 Vue 3 引入 Composition API的寫法,當我們引入一個 hooks 函數的時候其實就像在 vue2 中使用一個 mixin 一樣,hooks 函數中的ref,reactive就相當於 mixin 中的data,同時 hooks 還可以引入一些生命週期函數,watch 等在 mixin 中都有體現。下面展示一下 mixin 的寫法,這裡不過多的講解 mixin

export const mixins = {
  data() {
    return {
      msg: "",
    };
  },
  computed: {},
  created() {
    console.log("我是mixin中的created生命週期函數");
  },
  mounted() {
    console.log("我是mixin中的mounted生命週期函數");
  },
  methods: {
    clickMe() {
      console.log("我是mixin中的點選事件");
    },
  },
};

元件中引入

export default {
  name: "App",
  mixins: [mixins],
  components: {},
  created() {
    console.log("元件呼叫minxi資料", this.msg);
  },
  mounted() {
    console.log("我是元件的mounted生命週期函數");
  },
};

用過 vue2 的 mixin 的都知道它雖然可以封裝一些邏輯,但是它同時也帶來了一些問題.比如你引入多個 mixin 它們的 data,methods 命名可能會衝突,當 mixin 多了可能會出現維護性問題,另外 mixin 不是一個函數,因此不能傳遞引數來改變它的邏輯,具有一定的侷限性等,但這些問題到了 vue3 的 hooks 中則迎刃而解

hooks 中生命週期執行順序

hooks 中生命週期與元件中的生命週期執行順序其實很好判斷,就看它們誰的同級生命週期函數先建立那就先執行誰的,比如在 useAdd 中加幾個生命週期

import { ref, onMounted, onBeforeUnmount, onUnmounted } from "vue";
export const useAdd = () => {
  const a = ref(1);
  setInterval(() => {
    a.value++;
  }, 1000);
  onMounted(() => {
    console.log("hooks---onMounted");
  });
  onBeforeUnmount(() => {
    console.log("hooks---onMounted");
  });
  onUnmounted(() => {
    console.log("hooks---onUnmounted");
  });

  return a;
};

然後在元件中也引入這些生命週期

<template>
  <div>{{ a }}</div>
</template>

<script lang='ts' setup>
import { useAdd } from "../hooks/useTest"
import { onMounted, onBeforeUnmount, onUnmounted } from "vue";

onMounted(() => {
  console.log("元件---onMounted");
});
onBeforeUnmount(() => {
  console.log("元件---onMounted");
});
onUnmounted(() => {
  console.log("元件---onUnmounted");
});
const a = useAdd()
</script>

如果將 hooks 放到最後那麼它們的順序是這樣的

如果放到前面那就是這樣的

ok,vue3 的 hooks 就介紹這些,接下來我們寫兩個實際應用中的 hooks 函數讓大家體驗一下

封裝一個傳送簡訊驗證碼倒計時 hooks

我們先直接在元件中實現一個傳送簡訊的功能,注意下面只寫了一些主要邏輯,很多細節並未處理

<template>
    <div>
        <input type="text" placeholder="請輸入驗證碼" v-model="code">
        <button @click="sendCode">{{ sendBtnText }}</button>
    </div>
</template>

<script lang='ts' setup>
import { ref } from 'vue';

const code = ref('')
const sendBtnText = ref('傳送驗證碼')
const countDownNum = ref(60)
const sendCode = () => {
    //這裡省略呼叫傳送簡訊介面邏輯,省略禁止點選邏輯
    sendBtnText.value = countDownNum.value + 's'
    const timer = setInterval(() => {
        countDownNum.value--
        sendBtnText.value = countDownNum.value + 's'
        if (countDownNum.value === 0) {
            clearInterval(timer)
            sendBtnText.value = '傳送驗證碼'
            countDownNum.value = 60
        }
    }, 1000)
}
</script>
<style lang="css">
button {
    font-size: 14px;
    background: #23A7F2;
    color: #fff;
}

input {
    height: 30px;
}
</style>

這裡邏輯很簡單,就是點選傳送按鈕開啟定時器出現倒計時的功能

假如我們還有其它地方用到傳送簡訊頁面,我們可以將簡訊傳送封裝成一個元件。但是如果其它頁面想要使用的傳送簡訊頁面和這個元件不一樣的話,我們就需要將它的邏輯抽離封裝成一個 hooks 函數了,下面我們就將這個倒計時功能封裝成一名為 useCountDown 的 hooks

import { Ref, ref } from "vue";
export default (
  downNum: number
): ({ sendBtnText: Ref<string>, sendCode: () => void }) => {
  const sendBtnText = ref("傳送驗證碼");
  const countDownNum = ref(downNum);

  //這裡省略呼叫傳送簡訊介面邏輯,省略禁止點選邏輯
  const sendCode = () => {
    sendBtnText.value = countDownNum.value + "s";
    const timer = setInterval(() => {
      countDownNum.value--;
      sendBtnText.value = countDownNum.value + "s";
      if (countDownNum.value === 0) {
        clearInterval(timer);
        sendBtnText.value = "傳送驗證碼";
        countDownNum.value = downNum;
      }
    }, 1000);
  };
  return { sendBtnText, sendCode };
};

邏輯和上面一樣,只不過是返回了一個按鈕要顯示的文字以及一個點選傳送驗證碼呼叫的函數。然後在元件中使用

import { ref } from "vue";
import useCountDown from "../hooks/useCountDown";
const code = ref("");
const { sendBtnText, sendCode } = useCountDown(60);

這樣的話在其它元件中就也能夠使用它了

寫在最後

Vue 3中的Hooks函數是一個非常實用的功能,在元件開發中他能夠將一些通用邏輯抽離實現邏輯的複用,大大提高了我們程式碼的可讀性及可維護性。通過本篇文章相信大家已經對hooks的使用有了一定的理解,很多開源專案中都封裝了大量的hooks函數,大家可以去檢視學習他們是如何使用hooks函數的

都看到最後了,點個贊吧