可组合函数(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 组件中任何需要逻辑复用、状态管理、异步操作和事件处理的场景。它们特别适合以下几类需求:
- 逻辑复用:将某些功能模块化,使得多个组件可以共享相同的逻辑。
- 分离复杂逻辑:将复杂的业务逻辑拆解成小而易管理的部分,增强代码的可维护性和可读性。
- 代码组织优化:使代码组织更加灵活和模块化,减少组件中的重复代码。
这种模式不仅提升了代码的复用性,还提高了应用的维护性和扩展性。