Vue3 自定义hook函数

使用场景

Vue3中,使用什么API就引入,这个就是组合式 API

然而,有时引入很多的API就不利于代码的阅读。
所以,在 Vue3 中新增了 Hook,可以通过自定义hook函数来存放组合式API的东西,在需要的时候再进行引用。

概念

hook :其本质是一个函数,把 setup 函数中使用的 Composition API 放到一个文件中进行了封装,然后在需要用到的地方,进行引入,类似于 vue2.x 中的 mixin

自定义hook的优势

自定义 hook 能够复用代码,让setup中的逻辑更清楚易懂。

实例

TestPage.vue

<template>
  <p>The title is:{{ title }}</p>
  <p>The currt count is:{{ currCount }}</p>
  <a-button @click="plusCount(3)" type="primary">click me plus count</a-button>
  <a-button @click="minusCount()">click me minus count</a-button>
  <a-button @click="set(5)" type="danger">click me set count</a-button>
  <a-button @click="reset" type="dashed">click me reset count</a-button>
</template>

<script lang="ts">
import { ref } from 'vue'
import setCount from './hook/setCount'

export default {
  name: 'test',
  props: {
    msg: String,
  },
  setup() {
    const title = ref('This is test page')
    const {
      current: currCount,
      plusCount,
      minusCount,
      set,
      reset,
    } = setCount(2, {
      min: 1,
      max: 15,
    })

    return {
      title,
      currCount,
      plusCount,
      minusCount,
      set,
      reset,
    }
  },
}
</script>

/hook/setCount.ts:

import { ref, Ref, watch } from 'vue'
// 使用 interface 接口定义入参Range 
interface Range {
  min?: number,
  max?: number
}

// 使用 interface 接口定义返回Result  
interface Result {
  current: Ref<number>,
  plusCount: (delta?: number) => void,
  minusCount: (delta?: number) => void,
  set: (value: number) => void,
  reset: () => void
}

export default function useCount(initialVal: number, range?: Range): Result {
  const current = ref(initialVal)
  const plusCount = (delta?: number): void => {
    if (typeof delta === 'number') {
      current.value += delta
    } else {
      current.value += 1
    }
  }
  const minusCount = (delta?: number): void => {
    if (typeof delta === 'number') {
      current.value -= delta
    } else {
      current.value -= 1
    }
  }
  const set = (value: number): void => {
    current.value = value
  }
  const reset = () => {
    current.value = initialVal
  }
  
  watch(current, (newVal: number, oldVal: number) => {
    if (newVal === oldVal) {
      return
    }
    if (range && range.min && newVal < range.min) {
      current.value = range.min
    } else if (range && range.max && newVal > range.max) {
      current.value = range.max
    }
  })

  return {
    current,
    plusCount,
    minusCount,
    set,
    reset
  }
}

Vue3 自定义hook函数_第1张图片

有时候,一个组件里面可能会使用多个 hook,如下:

/hook/setStudent.ts:

import { reactive } from "vue";

export default function() {
  let student = reactive({
    name: "xiao ming",
    age:18,  
    changeInfomation() {
      student.name = "xiaofang"
      student.age = 20
    }
  })

  return student;
}

修改 TestPage.vue:

<template>
  <p>The title is:{{ title }}</p>
  <p>The student name is:{{stu.name}}</p>
  <p>The student age is:{{stu.age}}</p>
  <a-button @click="stu.changeInfomation" type="primary">click me change the student's information</a-button>
  <p>The currt count is:{{ currCount }}</p>
  <a-button @click="plusCount(3)" type="primary">click me plus count</a-button>
  <a-button @click="minusCount()">click me minus count</a-button>
  <a-button @click="set(5)" type="danger">click me set count</a-button>
  <a-button @click="reset" type="dashed">click me reset count</a-button>
</template>

<script lang="ts">
import { ref } from 'vue'
import setCount from './hook/setCount'
import setStudent from './hook/setStudent'

export default {
  name: 'test',
  props: {
    msg: String,
  },
  setup() {
    const title = ref('This is test page')
    const {
      current: currCount,
      plusCount,
      minusCount,
      set,
      reset,
    } = setCount(2, {
      min: 1,
      max: 15,
    })

    return {
      title,
      currCount,
      plusCount,
      minusCount,
      set,
      reset,
      stu: setStudent(),
    }
  },
}
</script>

页面效果:
Vue3 自定义hook函数_第2张图片

Hook 的特征之一:可以在组件外去写一些自定义 Hook,所以,不仅可以在.vue组件内部使用Vue的能力,而且,在任意的文件下(如setCount.ts)下也可以。

你可能感兴趣的:(#,Vue,3,javascript,vue.js,typescript)