Vue3 的Hooks, 即“组合式函数”(Composables) 在项目中的使用
什么是“组合式函数”?
在 Vue 应用的概念中,“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。
当构建前端应用时,我们常常需要复用公共任务的逻辑。例如为了在不同地方格式化时间,我们可能会抽取一个可复用的日期格式化函数。这个函数封装了无状态的逻辑:它在接收一些输入后立刻返回所期望的输出。复用无状态逻辑的库有很多,比如你可能已经用过的 lodash 或是 date-fns。
相比之下,有状态逻辑负责管理会随时间而变化的状态。一个简单的例子是跟踪当前鼠标在页面中的位置。在实际应用中,也可能是像触摸手势或与数据库的连接状态这样的更复杂的逻辑。
从 Vuejs
官网抄的简介, 移步官网查看更详细说明 what-is-a-composable
我个人对 Vue
的 Hooks
的浅薄理解
- 是一个以
use
开头命名的函数, 比如useCount
- 该函数内部可以使用
ref
,reactive
,computed
,onMounted
等响应式方法工具或生命周期函数钩子 - 该函数会返回具有响应式的变量、函数方法
Hooks
可以在多个不同页面直接导入使用, 就跟一个工具函数差不多Hooks
和utils
中的工具函数, 我觉得区别就是返回的变量是否有响应式Hooks
实际就是把页面的部分代码提取了在一个函数中, 通过导入的方式嵌入
的原代码中执行
理解很浅,就这么多吧,哪里写得不对,感谢指出!
初次了解 Hooks
最近用 Vue3 + vant
从零开始做一个移动端的项目, 项目不算大, 但项目1期的开发时间非常紧, 根本没有时间去把代码写得好看一些, 虽然分成了许多组件, 但代码仍然是写得又长又臭, 还有许多重复的代码片段。
项目2期的开发时间宽裕了许多, 就可以多花一些时间把公共的代码提取出去。
一开始搜很多 Hook
相关的文章看, 大部分文章举的例子都是 useAdd
, useMouse
之类的例子, 一眼就能看懂了, 但是我项目中用不上这些东西呢? 所以我一开始写出来的 Hooks
是长这样的:
在 /src/hooks/useState.js
中
export function useState() {
const stateList = [
{ value: 0, label: '未提交', color: 'default' },
{ value: 1, label: '审批中', color: 'primary' },
{ value: 2, label: '已驳回', color: 'danger' },
{ value: 3, label: '已撤回', color: 'danger' },
{ value: 4, label: '审批通过', color: 'success' },
{ value: 5, label: '关闭', color: 'default' },
];
const getState = (state) => {
const item = reimburseState.find((item) => item.value === state);
return {
label: item ? item.label : '',
color: item ? item.color : 'default',
};
};
return {
stateList,
getState,
};
}
在 list.vue
中使用
<script setup>
import { useState } from '@/hooks/useState';
const { stateList, getState } = useState();
// xxx
</script>
写的时候我心中也有疑问, 这不就是一个普通的 utils
函数吗, 为何叫 Hooks
?
等我把代码写得越来越臭, 我就确认了这确实是一个普通的 utils
, 真正的 Hooks
应该是响应式的;
我项目中的 Hooks
我这个移动端的项目中, 有很多个页面都用到了一个部门列表的下拉框, 部门列表的数据需要通过接口请求才拿到, 一开始的写法, 在 A 页面写一遍接口调用, B 页面Ctrl C/V一遍, C页面Ctrl C/V一遍, 需要修改的时候一个个页面去修改, 我又不想把它封装成一个组件(组件间的交互让我觉得有些乏味), 这时候可以使用 Hooks
实现1: 获取部门列表
在 /hooks/useDepartmentList.js
中
import { getDepartmentList } from '@/api/common';
export function useDepartmentList() {
const showPicker = ref(false);
const departmentList = ref([]);
const loading = ref(false);
const getList = async () => {
loading.value = true;
const { data } = await getDepartmentList();
loading.value = false;
if (data.code === 200) {
departmentList.value = data.data;
}
};
onMounted(getList);
return { showPicker, departmentList, loading };
}
在 A.vue
页面中使用
<template>
<van-field
v-model="formState.departmentName"
name="departmentName"
is-link
readonly
label="所属部门"
placeholder="请选择所属部门"
:rules="[{ required: true, message: '请选择所属部门' }]"
required
@click="showPicker = true"
/>
<van-popup v-model:show="showPicker" round position="bottom">
<van-picker
:columns="departmentList"
:loading="loading"
@cancel="showPicker = false"
@confirm="onPickerConfirm"
/>
</van-popup>
</template>
import { useDepartmentList } from '@/hooks/useDepartmentList'; // 导入
const formState = reactive({
departmentId: '',
departmentName: '',
});
const { showPicker, departmentList, loading } = useDepartmentList(); // 使用
const onPickerConfirm = ({ selectedOptions }) => {
// 这个方法逻辑也可以处理到 `useDepartmentList` 函数中
};
实现2: 获取数据统计, 接口需要在页面中调用
在 /hooks/useCount.js
中
import { getCountApi } from '@/api/common';
export function useCount() {
const countValue = ref(0);
const getCount = async () => {
const { data } = await getCountApi();
if (data.code === 200) {
countValue.value = data.data;
}
};
return { countValue, getCount };
}
在 A.vue
页面中使用
<template>
{{ countValue }}
</template>
import { useCount } from '@/hooks/useCount'; // 导入
const { countValue, getCount } = useCount();
onMounted(getCount);
在已缓存的 B.vue
页面中使用
// ...
onActivated(getCount);
结尾
举的例子比较简单, 但我想已经把 Hooks
的用法和与Utils
工具函数的区别写清楚了的。
我目前这个项目中, 写的Hooks
代码最多的一个useXxx.js
有128行, 共有两个页面使用了这个useXxx.js
,相比两个页面都有这么大坨的重复代码, 令我感到非常舒服。
突然想到去年做的那个项目, 好多个页面都重复写了短信验证码相关的一大坨代码, 我得去优化下...
转载自:https://juejin.cn/post/7373955162128203803