useMagical 钩子函数文档
一、功能概述
useMagical 是一个响应式数据变更收集钩子,用于追踪对象数据源 source 的属性变化,并返回修改后的属性集合 result。支持初始化指定固定属性,适用于表单数据收集、对象变更监控、差异化数据同步等场景。
二、核心特性
深度克隆与变更追踪
- 基于
cloneDeep深度克隆原始数据,确保变更检测的准确性 - 自动对比数据源与缓存数据,仅记录发生变化的属性
- 基于
灵活的初始化配置
- 通过
initKey指定需要始终返回的初始化属性(即使未发生变更) - 支持动态传入初始缓存数据(
startMagical(val))
- 通过
响应式结果集
result为响应式对象,属性变化时自动触发视图更新- 仅包含变更属性或初始化指定属性,避免冗余数据
三、参数说明
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
source | Record<string, any> | 是 | 目标数据源对象(需为响应式对象或普通对象) |
initKey | string[] | 否 | 初始化需要固定返回的属性数组(如 ['id', 'name']) |
四、返回值说明
| 名称 | 类型 | 说明 |
|---|---|---|
source | Record<string, any> | 原始数据源(只读,建议通过响应式引用传入) |
result | Reactive<Record<string, any>> | 变更结果集(仅包含变化属性或 initKey 指定属性) |
startMagical | (val?: Record<string, any>) => void | 启动变更追踪方法(需手动调用) |
五、使用流程
graph TD A('调用 startMagical') --> B('初始化 sourceCache') B --> C{是否传入 initKey?} C -->|是| D('将 initKey 属性写入 result') C -->|否| E('等待 source 属性变更') F('source 属性变更') --> G('对比 source 与 sourceCache') G --> H('变更属性写入 result')
六、典型使用示例
场景 1:表单数据变更收集
vue
<template>
<div>
<input v-model="form.name" placeholder="姓名" />
<input v-model="form.age" placeholder="年龄" />
<button @click="startCollect">开始收集变更</button>
<div>变更结果:{{ result }}</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useMagical } from '@eco-library/hooks';
// 表单数据源
const form = ref({
name: '张三',
age: 18,
email: 'zhangsan@example.com'
});
// 初始化指定需要返回的属性(name 和 age)
const { result, startMagical } = useMagical(form, ['name', 'age']);
const startCollect = () => {
startMagical(); // 启动变更追踪
};
</script>场景 2:动态数据源初始化
typescript
// 动态传入初始缓存数据
const source = reactive({ a: 1, b: 2, c: 3 });
const { result, startMagical } = useMagical(source);
// 以 { b: undefined, c: undefined } 作为初始缓存
startMagical({ b: undefined, c: undefined });
// 修改 source.b 时,result.b 会被记录;修改 source.a 则不会(未在初始缓存中)场景 3:复杂对象变更监控
vue
<template>
<div>
<button @click="updateComplexData">修改深层数据</button>
<div>变更结果:{{ result }}</div>
</div>
</template>
<script setup>
import { reactive } from 'vue';
import { useMagical } from '@eco-library/hooks';
const source = reactive({
user: {
info: { name: 'Alice', age: 25 },
settings: { theme: 'light' }
}
});
const { result, startMagical } = useMagical(source);
const updateComplexData = () => {
source.user.info.age = 26; // 触发变更
source.user.settings.theme = 'dark'; // 触发变更
};
// 初始化时不指定 initKey,仅记录实际变更的属性
onMounted(() => {
startMagical();
});
</script>七、注意事项
数据源响应式要求
- 若传入普通对象(非响应式),需确保通过
reactive或ref包装,否则变更可能无法被检测。
- 若传入普通对象(非响应式),需确保通过
性能考量
- 深度克隆(
xCloneDeep)可能对大型对象造成性能开销,建议用于中小型对象场景。 - 避免在高频变更场景中使用(如动画帧回调)。
- 深度克隆(
数据类型限制
- 当前版本仅支持对象类型数据源,不建议传入数组或原始类型值。
八、扩展建议
1. 支持数组类型
typescript
// 扩展版本(伪代码)
export function useMagical(source: any, initKey?: string[] | number[]) {
// 新增数组索引处理逻辑
function isArrayKey(key: string) {
return /^\d+$/.test(key);
}
watchEffect(() => {
if (!starting.value) return;
if (Array.isArray(source)) {
source.forEach((item, index) => {
if (JSON.stringify(item) !== JSON.stringify(sourceCache[index])) {
result[index] = item;
}
});
}
// ... 原有对象处理逻辑
});
}2. 添加变更回调
typescript
export function useMagical(source: any, initKey?: string[], onChanged?: (changes: any) => void) {
// ... 原有逻辑
watchEffect(() => {
if (!starting.value) return;
const changes = computeChanges(source, sourceCache);
result.value = changes;
onChanged?.(changes); // 触发变更回调
});
}九、依赖说明
- 核心依赖:Vue 3.x(
reactive、watchEffect) - 类型支持:建议为
source添加类型声明,提升类型安全性
