各位观众老爷,晚上好!今儿咱们聊聊Vue 3 Composition API 里头,怎么玩转自定义 Composable 函数。这玩意儿,说白了,就是把一堆逻辑攒成一个函数,然后在不同的组件里复用。听起来是不是有点像“祖传秘方”?
一、啥是Composable?为啥要用它?
在Vue 2的Options API里,逻辑往往分散在data
、methods
、computed
等等选项里,组件稍微复杂点,代码就跟“千层饼”似的,揉成一团,难以维护和复用。
Composable 就好比“模块化装修”,把不同的功能模块(比如处理用户输入、网络请求、动画效果)封装成一个个独立的函数,哪个组件需要,直接“插”进去就行了,清晰又高效。
用人话说,Composable 就是:
- 代码复用: 一份逻辑,到处使用,告别复制粘贴。
- 逻辑组织: 功能内聚,代码结构清晰,维护起来心情舒畅。
- 可测试性: 独立的Composable 函数,更容易进行单元测试。
二、Composable 函数的“套路”
一个 Composable 函数,通常遵循以下几个步骤:
- 定义函数: 函数名通常以
use
开头,比如useMousePosition
、useCounter
。 - 引入依赖: 使用
ref
、reactive
、computed
等 Vue 提供的 API 来管理状态和计算属性。 - 编写逻辑: 在函数内部实现具体的业务逻辑。
- 返回响应式数据: 将需要暴露给组件的状态和方法,以对象的形式返回。
三、实战演练:编写一个 useMousePosition
Composable
咱们来编写一个获取鼠标位置的 Composable 函数 useMousePosition
:
import { ref, onMounted, onUnmounted } from 'vue';
export function useMousePosition() {
const x = ref(0);
const y = ref(0);
function updatePosition(event) {
x.value = event.clientX;
y.value = event.clientY;
}
onMounted(() => {
window.addEventListener('mousemove', updatePosition);
});
onUnmounted(() => {
window.removeEventListener('mousemove', updatePosition);
});
return {
x,
y,
};
}
代码解读:
ref(0)
:创建两个响应式变量x
和y
,初始值为 0。updatePosition(event)
:更新鼠标位置的回调函数。onMounted()
:在组件挂载后,添加mousemove
事件监听器。onUnmounted()
:在组件卸载前,移除mousemove
事件监听器,防止内存泄漏。return { x, y }
:返回包含x
和y
的对象,供组件使用。
四、在组件中使用 useMousePosition
现在,咱们在一个组件中使用 useMousePosition
:
<template>
<div>
<p>鼠标位置:X: {{ x }}, Y: {{ y }}</p>
</div>
</template>
<script>
import { useMousePosition } from './useMousePosition';
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const { x, y } = useMousePosition();
return {
x,
y,
};
},
});
</script>
代码解读:
import { useMousePosition } from './useMousePosition'
:引入useMousePosition
函数。const { x, y } = useMousePosition()
:调用useMousePosition
函数,获取x
和y
变量。return { x, y }
:将x
和y
变量暴露给模板。{{ x }}, {{ y }}
:在模板中显示鼠标位置。
五、进阶技巧:Composable 函数的参数和返回值
Composable 函数可以接收参数,也可以返回更复杂的数据结构。
1. 接收参数
假设我们需要一个可以自定义更新频率的 useMousePosition
函数:
import { ref, onMounted, onUnmounted } from 'vue';
export function useMousePosition(interval = 100) { // 添加 interval 参数,默认 100ms
const x = ref(0);
const y = ref(0);
let timer = null;
function updatePosition(event) {
x.value = event.clientX;
y.value = event.clientY;
}
onMounted(() => {
timer = setInterval(() => {
updatePosition({ clientX: document.body.clientWidth * Math.random(), clientY: document.body.clientHeight * Math.random() }); // 模拟鼠标移动
}, interval);
});
onUnmounted(() => {
clearInterval(timer);
});
return {
x,
y,
};
}
在组件中使用:
<template>
<div>
<p>鼠标位置:X: {{ x }}, Y: {{ y }}</p>
</div>
</template>
<script>
import { useMousePosition } from './useMousePosition';
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const interval = ref(500);
const { x, y } = useMousePosition(interval.value);
return {
x,
y,
interval,
};
},
});
</script>
2. 返回复杂数据结构
Composable 函数可以返回对象、数组,甚至函数:
import { ref, onMounted, onUnmounted } from 'vue';
export function useCounter(initialValue = 0) {
const count = ref(initialValue);
function increment() {
count.value++;
}
function decrement() {
count.value--;
}
function reset() {
count.value = initialValue;
}
return {
count,
increment,
decrement,
reset,
};
}
在组件中使用:
<template>
<div>
<p>计数器:{{ count }}</p>
<button @click="increment">增加</button>
<button @click="decrement">减少</button>
<button @click="reset">重置</button>
</div>
</template>
<script>
import { useCounter } from './useCounter';
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const { count, increment, decrement, reset } = useCounter(10);
return {
count,
increment,
decrement,
reset,
};
},
});
</script>
六、最佳实践:Composable 函数的设计原则
- 单一职责: 一个 Composable 函数只负责一个特定的功能。
- 可配置性: 允许通过参数自定义 Composable 函数的行为。
- 可测试性: 编写单元测试,确保 Composable 函数的正确性。
- 命名规范: 函数名以
use
开头,清晰表达函数的功能。 - 文档: 编写详细的文档,说明 Composable 函数的功能、参数和返回值。
七、Composable 函数的应用场景
Composable 函数可以应用于各种场景:
- 表单处理: 验证用户输入、管理表单状态。
- 数据获取: 从 API 获取数据、缓存数据。
- 动画效果: 创建复杂的动画效果。
- 权限控制: 检查用户权限。
- 国际化: 处理多语言支持。
八、Composable 函数与 Vuex 的区别
Composable 函数和 Vuex 都是用于状态管理的工具,但它们的应用场景有所不同。
特性 | Composable 函数 | Vuex |
---|---|---|
状态管理范围 | 组件级别,适用于组件内部的状态管理,或者在少量组件之间共享状态。 | 应用级别,适用于需要在多个组件之间共享的全局状态。 |
代码复用 | 通过函数调用实现代码复用,更加灵活。 | 通过 Store 的 mutations 和 actions 实现代码复用,相对固定。 |
复杂性 | 相对简单,易于理解和使用。 | 相对复杂,需要理解 Store、mutations、actions、getters 等概念。 |
适用场景 | 组件内部状态管理、少量组件之间共享状态、简单的逻辑复用。 | 全局状态管理、多个组件之间共享状态、复杂的应用逻辑。 |
测试 | 方便单元测试,直接调用函数并验证返回值即可。 | 需要模拟 Vuex 环境进行测试,相对复杂。 |
简单来说,如果只是在几个组件之间共享状态,或者需要复用一些简单的逻辑,Composable 函数更合适。如果需要管理全局状态,并且应用逻辑比较复杂,Vuex 更加强大。
九、总结
Composable 函数是 Vue 3 Composition API 的核心特性之一,它提供了一种更加灵活和可维护的代码组织方式。掌握 Composable 函数的编写和使用,可以大大提高开发效率和代码质量。
记住,Composable 的精髓在于:模块化,复用,清晰!
希望今天的内容对大家有所帮助。溜了溜了~