【vue3】优雅的解决reactive()响应式对象初始化重新赋值问题v2

关联的上篇文章:

【vue3】优雅的解决reactive()响应式对象初始化重新赋值问题_vue3 reactive重新赋值_oumae-kumiko的博客-CSDN博客

在上面该文章提到了reactive该api的不方便之处和相关重置数据方法的解析。下面提供的方法就是自己封装的`$reactive`方法,通过该方法返回响应式数据和重置数据的方法。 

import { ref } from "vue";
import { isTypeof, deepClone } from "@utils/index";
import { ElMessage } from "element-plus";

interface $ReactiveOptions<K extends string | number | symbol, V> {
    data: V;
    reset: () => void;
}
type $Reactive = <V extends object, K extends keyof V>(data: V) => $ReactiveOptions<K, V>; 
export const $reactive: $Reactive = (data) => {
    let types = isTypeof(data);
    if (types !== "object") {
        ElMessage.error("$reactive函数传入参数错误,只允许传入普通object类型");
        return;
    }
    let originData = deepClone(data);
    let rData = ref(data);
    function reset() {
        for (const key in rData.value) {
            delete rData.value[key];
        }
        deepClone(originData, rData.value);
    }
    return {
        data: rData.value,
        reset,
    };
};
function clone(obj: object, target?: object) {
    if (typeof obj !== "object" || obj == null) {
        return obj;
    }
    let res;
    if (Array.isArray(obj)) {
        res = [];
    } else {
        res = {};
    }
    for (const key in obj) {
        if (target) {
            target[key] = clone(obj[key], target[key]);
        } else {
            res[key] = clone(obj[key]);
        }
    }
    return res;
}

// 第一个参数为被拷贝的对象;第二个参数为输出对象,若有第二个参数,则将拷贝对象的值直接赋给输出对象
type DeepClone = (data: object, target?: object) => object;
export const deepClone: DeepClone = (cloneData, target) => {
    if (typeof cloneData === "object" && cloneData !== null) {
        let obj = {};
        if (target) {
            clone(cloneData, target);
        } else {
            obj = clone(cloneData);
        }
        return obj;
    } else {
        alert("deepClone的参数请传入普通对象/数组");
    }
};
// 接收一个参数,返回一个字符串说明是哪个数据类型,且capsLook为1则大写开头,非1或不传则小写开头 //! 警告:最好统一小写,避免维护麻烦和快速认知相关代码
type IsTypeof = (data: any, capsLook?: number) => string;
export const isTypeof: IsTypeof = (data, capsLook) => {
    let str = Object.prototype.toString.call(data);
    str = str.match(/\[object (\S*)\]/)[1];
    str = capsLook ? str.toUpperCase() : str.toLowerCase();
    return str;
};

QQ交流群:522976012  ,欢迎来玩。

聚焦vue3,但不限于vue,任何前端问题,究其本质,值得讨论,研究与学习。

猜你喜欢

转载自blog.csdn.net/lijiahui_/article/details/129347078