#用于跟踪和反映数据源对象的变化--useMagical

import { cloneDeep } from 'lodash-es'
import { reactive, ref, watchEffect } from 'vue'
/**
 * 神奇函数
 * @param source 数据源,
 * @param initKey 固定需要返回的属性
 * @description 收集数据源中修改的属性,并返回
 * @version 1.0 仅支持对象
 * @author sufei
 * @return { source, result }
 */
export function useMagical(source: any, initKey?: string[]) {
  const result = reactive<any>({})
  // 神奇函数启动状态
  const starting = ref(false)

  // 对数据源进行深度copy
  let sourceCache: any = {}

  watchEffect(() => {
    if (!starting.value) return
    Object.keys(sourceCache).forEach((key) => {
      if (JSON.stringify(source[key]) !== JSON.stringify(sourceCache[key])) {
        result[key] = source[key]
      } else if (initKey?.includes(key)) {
        result[key] = source[key]
      }
    })
  })

  /* 启动神奇函数*/
  function startMagical(val?: Record<string, any>) {
    if (val) {
      setSourceCache(val)
    } else {
      sourceCache = cloneDeep(source)
    }
    if (initKey && initKey.length > 0) {
      initKey.forEach((key) => {
        result[key] = source[key] || null
      })
    }
    starting.value = true
  }

  function setSourceCache(val: any) {
    sourceCache = {}
    Object.keys(val).forEach((key) => {
      sourceCache[key] = undefined
    })
  }

  return {
    source,
    result,
    startMagical,
  }
}

这个 useMagical 函数是一个自定义的 Vue Hooks,用于跟踪和反映数据源对象的变化。它通过 watchEffect 监听 source 的变化,并将变化的属性反映到 result 中。

问题分析:

类型安全问题source 参数的类型被声明为 any,这可能导致类型检查失效。应该使用更具体的类型来确保类型安全。
**副作用控制问题:**在 watchEffect 中直接修改 result,这可能导致不必要的副作用。应该使用更可控的方式来更新 result
性能问题:在每次 source 变化时,都会遍历 sourceCache 的所有键,这可能在数据源较大时影响性能。可以考虑使用更高效的算法来减少不必要的遍历。

修复建议:

**类型安全: **使用 TypeScript 的类型系统来确保 sourceresult 的类型安全。可以使用 Record<string, any> 或更具体的类型来定义 sourceresult
副作用控制: 使用 reactiveref 来创建响应式对象,并使用 Vueset 方法来更新 result,以避免直接修改响应式对象。
性能优化: 使用 Map 来存储 sourceCache,这样可以更高效地查找和更新键值对。同时,可以使用 watch 来监听特定的属性,而不是整个 source 对象。

import { cloneDeep, isEqual } from 'lodash-es';
import { reactive, ref, watchEffect } from 'vue';

/**
 * 神奇函数
 * @param source 数据源,
 * @param initKey 固定需要返回的属性
 * @description 收集数据源中修改的属性,并返回
 * @version 1.0 仅支持对象
 * @author sufei
 * @return { source, result }
 */
export function useMagical<T extends Record<string, any>>(source: T, initKey?: string[]) {
  const result = reactive<T>({} as T);
  // 神奇函数启动状态
  const starting = ref(false);

  // 对数据源进行深度copy
  const sourceCache = ref<T>({} as T);

  watchEffect(() => {
    if (!starting.value) return;
    Object.keys(source).forEach((key) => {
      if (!isEqual(source[key], sourceCache.value[key])) {
        result[key] = source[key];
      } else if (initKey?.includes(key)) {
        result[key] = source[key];
      }
    });
  });

  /* 启动神奇函数*/
  function startMagical(val?: T) {
    if (val) {
      setSourceCache(val);
    } else {
      sourceCache.value = cloneDeep(source);
    }
    if (initKey && initKey.length > 0) {
      initKey.forEach((key) => {
        result[key] = source[key] || null;
      });
    }
    starting.value = true;
  }

  function setSourceCache(val: T) {
    sourceCache.value = {} as T;
    Object.keys(val).forEach((key) => {
      sourceCache.value[key] = undefined;
    });
  }

  return {
    source,
    result,
    startMagical,
  };
}

修复说明:
类型安全:
使用 T extends Record<string, any> 来确保 sourceresult 是对象类型。
使用 reactive<T>({} as T)ref<T>({} as T) 来确保类型安全。
副作用控制:
使用 reactiveref 来创建响应式对象。
使用watchEffect 来监听 source 的变化,并使用 isEqual 来比较值是否相等。
性能优化:
使用 ref 来存储 sourceCache,并在 startMagical 函数中使用 cloneDeep 来深度复制 source

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值