可组合函数(Composables)是 Vue 3 的组合式 API 中的一种设计模式,用于将可复用的逻辑封装成独立的函数,从而提高代码的模块化和复用性。可组合函数的核心目标是将复杂的逻辑拆分为小的、可管理的单元,然后在不同的组件中共享这些逻辑。
以下是可组合函数的典型应用场景和用法示例:
1. 状态管理
- 在一个应用中,不同的组件可能需要共享相同的状态(如用户登录信息、购物车状态等)。可组合函数可以用于集中管理这些状态,类似于轻量级的状态管理解决方案。
**应用场景:**登录状态的管理
// useAuth.js
import { ref } from 'vue';export function useAuth() {const isAuthenticated = ref(false);function login() {isAuthenticated.value = true;}function logout() {isAuthenticated.value = false;}return { isAuthenticated, login, logout };
}// 在组件中使用
import { useAuth } from './useAuth';export default {setup() {const { isAuthenticated, login, logout } = useAuth();return { isAuthenticated, login, logout };}
}
2. 表单处理
- 表单处理是前端开发中常见的需求,包括表单数据的双向绑定、验证和提交。通过可组合函数,表单处理逻辑可以被复用并适应不同的表单结构。
**应用场景:**表单数据和验证
// useForm.js
import { ref } from 'vue';export function useForm() {const formData = ref({name: '',email: ''});const validate = () => {return formData.value.name !== '' && formData.value.email.includes('@');};return { formData, validate };
}// 在组件中使用
import { useForm } from './useForm';export default {setup() {const { formData, validate } = useForm();const submit = () => {if (validate()) {// 提交表单逻辑console.log('Form is valid');}};return { formData, submit };}
}
3. 异步数据获取
- 在大型应用中,不同的组件可能需要获取相同的远程数据(如用户信息、列表数据等)。通过可组合函数,数据获取逻辑可以被封装并复用。
**应用场景:**数据获取和错误处理
// useFetchData.js
import { ref } from 'vue';export function useFetchData(url) {const data = ref(null);const error = ref(null);const loading = ref(true);const fetchData = async () => {try {const response = await fetch(url);data.value = await response.json();} catch (err) {error.value = err;} finally {loading.value = false;}};fetchData(); // 自动触发数据获取return { data, error, loading };
}// 在组件中使用
import { useFetchData } from './useFetchData';export default {setup() {const { data, error, loading } = useFetchData('https://api.example.com/items');return { data, error, loading };}
}
4. 事件处理和订阅
- 可组合函数可以用于封装事件处理逻辑,尤其是跨组件间共享的事件处理器。比如,处理窗口大小变化、滚动事件等。
**应用场景:**监听窗口大小变化
// useWindowSize.js
import { ref, onMounted, onUnmounted } from 'vue';export function useWindowSize() {const width = ref(window.innerWidth);const height = ref(window.innerHeight);const updateSize = () => {width.value = window.innerWidth;height.value = window.innerHeight;};onMounted(() => window.addEventListener('resize', updateSize));onUnmounted(() => window.removeEventListener('resize', updateSize));return { width, height };
}// 在组件中使用
import { useWindowSize } from './useWindowSize';export default {setup() {const { width, height } = useWindowSize();return { width, height };}
}
5. 处理业务逻辑和复杂交互
- 对于复杂的业务逻辑和交互处理,如处理权限验证、导航守卫等,可组合函数可以帮助将这些复杂的逻辑封装起来,增强代码的可复用性和可读性。
**应用场景:**权限验证逻辑封装
// usePermissions.js
import { ref } from 'vue';export function usePermissions() {const hasPermission = ref(false);const checkPermission = (user, action) => {// 假设我们有一个权限列表来验证用户的权限hasPermission.value = user.permissions.includes(action);};return { hasPermission, checkPermission };
}// 在组件中使用
import { usePermissions } from './usePermissions';export default {setup() {const { hasPermission, checkPermission } = usePermissions();const user = { permissions: ['view', 'edit'] };checkPermission(user, 'view'); // 检查用户权限return { hasPermission };}
}
6. 动画与样式处理
- 可组合函数也可以用于封装动画和样式处理逻辑,比如页面的淡入淡出效果、拖拽效果、滚动等。
**应用场景:**页面滚动监听
// useScroll.js
import { ref, onMounted, onUnmounted } from 'vue';export function useScroll() {const scrollY = ref(0);const handleScroll = () => {scrollY.value = window.scrollY;};onMounted(() => window.addEventListener('scroll', handleScroll));onUnmounted(() => window.removeEventListener('scroll', handleScroll));return { scrollY };
}// 在组件中使用
import { useScroll } from './useScroll';export default {setup() {const { scrollY } = useScroll();return { scrollY };}
}
7. 与外部库的结合
- 可组合函数不仅限于应用内部的逻辑封装,它们也可以与外部库结合使用。例如,封装第三方 UI 库或数据处理库的调用。
**应用场景:**与第三方地图库结合
// useGoogleMap.js
import { onMounted, ref } from 'vue';export function useGoogleMap(apiKey) {const map = ref(null);onMounted(() => {// 初始化 Google 地图map.value = new google.maps.Map(document.getElementById('map'), {center: { lat: -34.397, lng: 150.644 },zoom: 8});});return { map };
}// 在组件中使用
import { useGoogleMap } from './useGoogleMap';export default {setup() {const { map } = useGoogleMap('your-google-maps-api-key');return { map };}
}
总结
可组合函数的应用场景非常广泛,几乎可以适用于 Vue 组件中任何需要逻辑复用、状态管理、异步操作和事件处理的场景。它们特别适合以下几类需求:
- 逻辑复用:将某些功能模块化,使得多个组件可以共享相同的逻辑。
- 分离复杂逻辑:将复杂的业务逻辑拆解成小而易管理的部分,增强代码的可维护性和可读性。
- 代码组织优化:使代码组织更加灵活和模块化,减少组件中的重复代码。
这种模式不仅提升了代码的复用性,还提高了应用的维护性和扩展性。