Skip to content

useMagical 钩子函数文档

一、功能概述

useMagical 是一个响应式数据变更收集钩子,用于追踪对象数据源 source 的属性变化,并返回修改后的属性集合 result。支持初始化指定固定属性,适用于表单数据收集、对象变更监控、差异化数据同步等场景。

二、核心特性

  1. 深度克隆与变更追踪

    • 基于 cloneDeep 深度克隆原始数据,确保变更检测的准确性
    • 自动对比数据源与缓存数据,仅记录发生变化的属性
  2. 灵活的初始化配置

    • 通过 initKey 指定需要始终返回的初始化属性(即使未发生变更)
    • 支持动态传入初始缓存数据(startMagical(val)
  3. 响应式结果集

    • result 为响应式对象,属性变化时自动触发视图更新
    • 仅包含变更属性或初始化指定属性,避免冗余数据

三、参数说明

参数名类型必填说明
sourceRecord<string, any>目标数据源对象(需为响应式对象或普通对象)
initKeystring[]初始化需要固定返回的属性数组(如 ['id', 'name']

四、返回值说明

名称类型说明
sourceRecord<string, any>原始数据源(只读,建议通过响应式引用传入)
resultReactive<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>

七、注意事项

  1. 数据源响应式要求

    • 若传入普通对象(非响应式),需确保通过 reactiveref 包装,否则变更可能无法被检测。
  2. 性能考量

    • 深度克隆(xCloneDeep)可能对大型对象造成性能开销,建议用于中小型对象场景。
    • 避免在高频变更场景中使用(如动画帧回调)。
  3. 数据类型限制

    • 当前版本仅支持对象类型数据源,不建议传入数组或原始类型值。

八、扩展建议

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(reactivewatchEffect
  • 类型支持:建议为 source 添加类型声明,提升类型安全性

仅供内部学习使用