| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- import type { Dropdown } from "@/types";
- import type { InjectionKey } from "vue";
- export const DROPDOWN_SYMBOL = Symbol('DROPDOWN_SYMBOL') as InjectionKey<ReturnType<typeof useDropdown>>;
- /**
- * 深拷贝一个值
- * @param value 要拷贝的值
- * @returns 深拷贝后的值
- */
- const deepClone = (value: any): any => {
- // 如果是基本类型或 null/undefined,直接返回
- if (value == null || typeof value !== 'object') {
- return value;
- }
- // 如果是数组,递归拷贝每个元素
- if (Array.isArray(value)) {
- return value.map(item => deepClone(item));
- }
- // 如果是对象,递归拷贝所有属性
- const cloned: Record<string, any> = {};
- for (const key in value) {
- if (Object.prototype.hasOwnProperty.call(value, key)) {
- cloned[key] = deepClone(value[key]);
- }
- }
- return cloned;
- };
- /**
- * 深度比较两个值是否严格相等
- * @param a 第一个值
- * @param b 第二个值
- * @returns 是否相等
- */
- const deepEqual = (a: any, b: any): boolean => {
- // 如果引用相同,直接返回 true
- if (a === b) return true;
- // 如果其中一个为 null 或 undefined
- if (a == null || b == null) return a === b;
- // 如果类型不同,返回 false
- if (typeof a !== typeof b) return false;
- // 如果是基本类型(非对象),直接比较
- if (typeof a !== 'object') return a === b;
- // 如果是数组
- if (Array.isArray(a) && Array.isArray(b)) {
- if (a.length !== b.length) return false;
- return a.every((item, index) => deepEqual(item, b[index]));
- }
- // 如果一个是数组,另一个不是,返回 false
- if (Array.isArray(a) || Array.isArray(b)) return false;
- // 如果是对象,比较所有键值对
- const keysA = Object.keys(a);
- const keysB = Object.keys(b);
- // 键的数量不同,返回 false
- if (keysA.length !== keysB.length) return false;
- // 检查所有键是否都存在且值相等
- for (const key of keysA) {
- if (!keysB.includes(key)) return false;
- if (!deepEqual(a[key], b[key])) return false;
- }
- return true;
- };
- export const useDropdown = (configs: Dropdown.DropdownItem[]) => {
- const list = computed(() => configs);
- const form = ref<Record<string, any>>({});
- const openIndex = ref<number>(-1);
- const open = (index: number) => {
- openIndex.value = index;
- }
- const close = () => {
- openIndex.value = -1;
- }
- const submit = (index: number, value: any) => {
- form.value = {
- ...form.value,
- [list.value[index].prop]: value
- };
- }
- const reset = (index: number) => {
- form.value = {
- ...form.value,
- [list.value[index].prop]: list.value[index].value
- };
- }
- const init = (initValue: Record<string, any>) => {
- form.value = { ...initValue };
- list.value.forEach(item => {
- item.value = initValue[item.prop] || item.value;
- });
- }
- return {
- init,
- form,
- openIndex,
- open,
- close,
- submit,
- reset,
- deepEqual,
- deepClone
- }
- }
|