在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
}
}
有时候,一个组件里面可能会使用多个 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>
Hook
的特征之一:可以在组件外去写一些自定义 Hook
,所以,不仅可以在.vue
组件内部使用Vue
的能力,而且,在任意的文件下(如setCount.ts
)下也可以。