Skip to content

支持任意 JavaScript 环境或框架

处理数据工具集

extractPropertyToArray

提取给定对象数组中所有指定属性的值

提取属性示例
是否排除空值
点击提取属性
查看代码
vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import { extractPropertyToArray } from 'buzzts'

interface Item {
  [key: string]: any; // 允许任意属性
}

const inputJson = ref<string>(JSON.stringify([{"id":1,"name":"Alice"}, {"id":2,"name":"Bob"}]));
const propertyKey = ref<string>('id');
const extractedKeys = ref<string[]>([]);
const excludeNil = ref<boolean>(true); // 用于控制开关的状态

const extractKeys = () => {
  try {
    const items: Item[] = JSON.parse(inputJson.value);
    extractedKeys.value = extractPropertyToArray(items, propertyKey.value, excludeNil.value);
  } catch (error) {
    alert('请输入有效的 JSON 格式数据!');
  }
};

const resultText = computed(() => {
  if (extractedKeys.value.length < 1) return "点击提取属性";
  return `extractPropertyToArray([${inputJson.value}], '${propertyKey.value}', ${excludeNil.value}) = ${extractedKeys.value}`;
});

</script>

<template>
  <div>
    <n-card title="提取属性示例">
      <n-space vertical>
        <div class="input-container">
          <n-input
            type="textarea"
            v-model:value="inputJson"
            placeholder='输入对象数组 (JSON 格式,例如: [{"key":1},{"key":2}])'
            :rows="5"
          />
          <n-input
            v-model:value="propertyKey"
            placeholder="要提取的属性名"
          />
        </div>
        <div class="switch-container">
          <span>是否排除空值</span>
          <n-switch v-model:value="excludeNil"/>
        </div>
        <n-button type="primary" @click="extractKeys">提取属性</n-button>
        <n-gradient-text type="info">{{ resultText }}</n-gradient-text>
      </n-space>
    </n-card>
  </div>
</template>

<style scoped>
textarea {
  width: 100%;
  height: 100px;
}
.input-container {
  display: flex;
  gap: 10px; /* 控制输入框之间的间距 */
}
.switch-container {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}

.switch-container span {
  margin-right: 5px;
  margin-left: 20px;
}
</style>

参数属性说明类型默认值
items对象数组,每个对象应包含可选的指定属性Array<T> | null | undefined
key要提取的属性名,类型为对象的键K
excludeNil是否排除 null 和 undefined,默认为 falsebooleanfalse
返回值说明
Array<T[K]>返回所有指定属性值的数组,如果未提供有效的 items,则返回空数组

  • 提取对象数组中所有指定属性的值,支持可选地排除 null 和 undefined 的项

arrayToObject

将字符串数组转换为对象数组,每个对象包含指定的属性,对应数组中的字符串可选地,排除值为 null 的项。

数组转换为对象示例
是否排除空值
点击转换数组
查看代码
vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import { arrayToObject } from 'buzzts'

const inputArray = ref<string[]>(['item1', 'item2', null]);
const propertyKey = ref<string>('key');
const excludeNil = ref<boolean>(false);
const convertedObjects = ref<{ [key: string]: string }[]>([]);

const convertArrayToObject = () => {
  convertedObjects.value = arrayToObject(inputArray.value, propertyKey.value, excludeNil.value);
};

const resultText = computed(() => {
  if (convertedObjects.value.length < 1) return "点击转换数组";
  return `arrayToObject(${JSON.stringify(inputArray.value)}, '${propertyKey.value}', ${excludeNil.value}) = ${JSON.stringify(convertedObjects.value)}`;
});

</script>

<template>
  <div>
    <n-card title="数组转换为对象示例">
      <n-space vertical>
        <div class="input-container">
          <n-input
            type="textarea"
            v-model:value="inputArray"
            placeholder="输入字符串数组 (JSON 格式,例如: ['item1', 'item2', null])"
            :rows="5"
          />
          <n-input
            v-model:value="propertyKey"
            placeholder="要设置的属性名"
          />
        </div>
        <div class="switch-container">
          <span>是否排除空值</span>
          <n-switch v-model:value="excludeNil"/>
        </div>
        <n-button type="primary" @click="convertArrayToObject">转换数组</n-button>
        <n-gradient-text type="info">{{ resultText }}</n-gradient-text>
      </n-space>
    </n-card>
  </div>
</template>

<style scoped>
textarea {
  width: 100%;
  height: 100px;
}
.input-container {
  display: flex;
  gap: 10px; /* 控制输入框之间的间距 */
}
.switch-container {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}

.switch-container span {
  margin-right: 5px;
  margin-left: 20px;
}
</style>

参数属性说明类型默认值
stringArray字符串数组,若输入为 nullundefined,将返回空数组T[] | null | undefined
key要设置的属性名,默认为 'key'string'key'
excludeNil是否排除 null 和 undefined,默认为 falsebooleanfalse
返回值说明
Array<{ [K in typeof key]: T }>返回对象数组,每个对象包含指定的属性,对应数组中的字符串

  • 将字符串数组转换为对象数组,支持可选地排除 null 的项

filterObject

根据操作类型选择或忽略对象的属性

对象属性过滤器
选择 (pick)
{ "a": 1, "c": 3 }
查看代码
vue
<script setup lang="ts">
import { ref, computed } from "vue";
import { filterObject } from 'buzzts';

// 定义输入对象和属性数组的默认值
const inputObject = ref('{"a": 1, "b": "2", "c": 3}');
const paths = ref('a, c');
const action = ref<'pick' | 'omit'>('pick');

const actionOptions = [
  { label: '选择 (pick)', value: 'pick' },
  { label: '忽略 (omit)', value: 'omit' },
];

// 计算过滤结果
const filteredResult = computed(() => {
  try {
    const object = JSON.parse(inputObject.value); // 将输入的 JSON 字符串解析为对象
    const pathArray = paths.value.split(',').map(path => path.trim()); // 将输入的属性数组转换为数组
    return filterObject(object, pathArray, action.value); // 调用 filterObject 函数
  } catch (error) {
    return '输入的对象格式不正确'; // 错误处理
  }
});
</script>

<template>
  <n-card title="对象属性过滤器">
    <n-divider>输入对象</n-divider>
    <n-input
      v-model:value="inputObject"
      placeholder="请输入对象(JSON 格式)"
      style="width: 100%;"
    />
    
    <n-divider>属性数组</n-divider>
    <n-input
      v-model:value="paths"
      placeholder="请输入属性数组(用逗号分隔)"
      style="width: 100%;"
    />
    
    <n-divider>操作类型</n-divider>
    <n-select v-model:value="action" :options="actionOptions" style="width: 100%;" />
    
    <n-divider>过滤结果</n-divider>
    <div>{{ filteredResult }}</div>
  </n-card>
</template>

<style>
/* 可选样式 */
</style>

参数属性说明类型默认值
object来源对象object
paths要被选中的或忽略的属性数组string[]
action操作类型,选择或忽略'pick' | 'omit'
返回值说明
object返回新对象

  • 根据操作类型选择或忽略对象的属性。
  • action'pick' 时,返回包含 paths 中指定属性的新对象。
  • action'omit' 时,返回不包含 paths 中指定属性的新对象。
  • 如果 object 为空,返回一个空对象。

toMappedArray

将对象数组映射为指定格式

数组转换为对象示例
包含键
包含值
是否排除空值
点击转换数组
查看代码
vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import { toMappedArray } from 'buzzts';

const inputArray = ref<string>("[{\"value\":\"item\", \"label\":\"null\"}, {\"value\":\"item1\", \"label\":\"Item 1\"}, {\"value\":\"item2\", \"label\":\"Item 2\"}]"); // JSON 字符串格式
const inKeyField = ref<string>('value');
const inValueField = ref<string>('label');
const outKeyField = ref<string>('key');
const outValueField = ref<string>('value');
const includeKey = ref<boolean>(true);
const includeValue = ref<boolean>(true);
const excludeNil = ref<boolean>(false);
const convertedObjects = ref<{ [key: string]: string }[]>([]);
const isValidJson = ref<boolean>(true); // 用于跟踪输入的有效性

const goToMappedArray = () => {
  try {
    const parsedArray = JSON.parse(inputArray.value) as Array<{ [key: string]: any }>;
    const filteredArray = excludeNil.value ? parsedArray.filter(item => item !== null && item !== undefined) : parsedArray;
    convertedObjects.value = toMappedArray(filteredArray, {
      inKeyField: inKeyField.value,
      inValueField: inValueField.value,
      outKeyField: outKeyField.value,
      outValueField: outValueField.value,
      includeKey: includeKey.value,
      includeValue: includeValue.value
    });
  } catch (error) {
    convertedObjects.value = [];
    console.error("无效的输入格式:", error);
  }
};

const resultText = computed(() => {
  if (convertedObjects.value.length < 1) return "点击转换数组";
  return `toMappedArray(${inputArray.value}, '${inKeyField.value}', '${inValueField.value}', '${outKeyField.value}', '${outValueField.value}', ${includeKey.value}, ${includeValue.value}, ${excludeNil.value}) = ${JSON.stringify(convertedObjects.value)}`;
});
</script>

<template>
  <div>
    <n-card title="数组转换为对象示例">
      <n-space vertical>
        <div class="input-container">
          <n-input
            type="textarea"
            v-model:value="inputArray"
            placeholder='输入字符串数组 (JSON 格式,例如: [{"value":"item1", "label":"Item 1"}, {"value":"item2", "label":"Item 2"}])'
            :rows="3"
            @input="validateJson(inputArray)"
          />
          <div v-if="!isValidJson" style="color: red;">输入的 JSON 格式无效,请检查。</div>
        </div>
        <n-input
          v-model:value="inKeyField"
          placeholder="输入键字段名 (例如: 'value')"
        />
        <n-input
          v-model:value="inValueField"
          placeholder="输入值字段名 (例如: 'label')"
        />
        <n-input
          v-model:value="outKeyField"
          placeholder="输出键字段名 (例如: 'key')"
        />
        <n-input
          v-model:value="outValueField"
          placeholder="输出值字段名 (例如: 'value')"
        />
        <div class="switch-container">
          <span>包含键</span>
          <n-switch v-model:value="includeKey" />
          <span>包含值</span>
          <n-switch v-model:value="includeValue" />
          <span>是否排除空值</span>
          <n-switch v-model:value="excludeNil"/>
        </div>
        <n-button type="primary" @click="goToMappedArray">转换数组</n-button>
        <n-gradient-text type="info">{{ resultText }}</n-gradient-text>
      </n-space>
    </n-card>
  </div>
</template>

<style scoped>
textarea {
  width: 100%;
  height: 100px;
}
.input-container {
  display: flex;
  gap: 10px; /* 控制输入框之间的间距 */
}

.switch-container {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}

.switch-container span {
  margin-right: 5px;
  margin-left: 20px;
}
</style>

参数属性说明类型默认值
items输入的对象数组Array<{ [key: string]: any }>nullundefined
options选项对象{ inKeyField?: string; inValueField?: string; outKeyField?: string; outValueField?: string; includeKey?: boolean; includeValue?: boolean; }{}
options.inKeyField输入的 key 字段名stringkey
options.inValueField输入的 value 字段名stringvalue
options.outKeyField输出的 key 字段名stringkey
options.outValueField输出的 value 字段名stringvalue
options.includeKey是否输出 keybooleantrue
options.includeValue是否输出 valuebooleantrue
options.excludeNil是否排除 nullundefined,默认为 falsebooleanfalse
返回值说明
Array<{ [outKeyField]: string; label?: string; [outValueField]?: string }>返回映射后的数组

  • 将输入的对象数组转换为指定格式的数组。
  • 如果输入为 nullundefined,返回一个空数组。
  • 通过可选的 options 对象,用户可以自定义输入和输出字段名,以及是否包含 key 和 value 字段。

findValueByKey

根据键和值查找对象的对应值

findValueByKey 示例
返回的字段值
未找到匹配的值
查看代码
vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import { findValueByKey } from 'buzzts';

// 设置默认值
const inputArray = ref<string>(JSON.stringify([{ id: '1', name: 'One' }, { id: '2', name: 'Two' }])); // 默认的 JSON 字符串
const searchKey = ref<string>('id'); // 默认查找键
const searchValue = ref<any>('1'); // 默认查找值
const returnKey = ref<any>(null);
const foundValue = ref<any>(null);

const findValue = () => {
  const parsedItems = JSON.parse(inputArray.value);
  if (returnKey.value === "") {
    returnKey.value = null;
  }
  foundValue.value = findValueByKey(parsedItems, searchKey.value, searchValue.value, returnKey.value);
};

const resultText = computed(() => {
  if (foundValue.value === null) return "未找到匹配的值";
  return `findValueByKey(${inputArray.value}, ${searchKey.value}, ${searchValue.value}, ${returnKey.value})= ${JSON.stringify(foundValue.value)}`;
});

</script>

<template>
  <n-card title="findValueByKey 示例">
    <n-space vertical>
      <div class="input-container">
        <n-input
          type="textarea"
          v-model:value="inputArray"
          placeholder="输入对象数组 (JSON 格式,例如: [{ id: '1', name: 'One' }, { id: '2', name: 'Two' }])"
          :rows="3"
        />
        <n-input
          v-model:value="searchKey"
          placeholder="要查找的键"
        />
        <n-input
          v-model:value="searchValue"
          placeholder="要查找的值"
        />
        <n-input
          v-model:value="returnKey"
          placeholder="返回的字段值"
        />
      </div>
      <n-button type="primary" @click="findValue">查找值</n-button>
      <n-gradient-text type="info">{{ resultText }}</n-gradient-text>
    </n-space>
  </n-card>
</template>

<style scoped>
textarea {
  width: 100%;
  height: 100px;
}
.input-container {
  display: flex;
  flex-direction: column;
  gap: 10px; /* 控制输入框之间的间距 */
}
</style>

参数属性说明类型默认值
items输入的对象数组Array<{ [key: string]: any }>null
key要查找的键string
value要查找的值any
returnKey要返回的特定键stringundefined
返回值说明
`anynull`

  • 根据指定的键和值在输入的对象数组中查找匹配的值。
  • 如果输入为 null 或未找到匹配项,返回 null
  • 如果提供了 returnKey,则返回匹配对象中指定键的值;否则返回整个匹配对象。

arrayAllExist

检测一个数组是否包含另一个数组中所有的值(内部使用new Set性能更好。该方法只针对基本数据类型,需要更复杂的场景可以用arrayAllExistDeep

查看代码
vue
<script setup lang="ts">
import { computed } from "vue";
import { arrayAllExist } from "buzzts";

let arr1 = [1, 2, "3", 4, 10];
let arr2 = [1, "3", 2];
let arr3 = [1, "3", 2, 8];

function stringify(val) {
  return JSON.stringify(val);
}

let firstText = computed(() => {
  return `${stringify(arr1)} ${
    arrayAllExist(arr1, arr2)
      ? "包含 " + stringify(arr2) + " 中所有的值"
      : "不包含 " + stringify(arr2) + " 中的所有值"
  }`;
});

let secondText = computed(() => {
  return `${stringify(arr1)} ${
    arrayAllExist(arr1, arr3)
      ? "包含 " + stringify(arr3) + " 中所有的值"
      : "不包含 " + stringify(arr3) + " 中的所有值"
  }`;
});
</script>

<template>
  <naive-theme>
    <n-space vertical className="mt-2">
      <n-gradient-text type="info">
        {{ firstText }}
      </n-gradient-text>
      <n-gradient-text type="info">
        {{ secondText }}
      </n-gradient-text>
    </n-space>
  </naive-theme>
</template>

接收二个参数,第一个参数 array,第二个参数 checkArray,返回值类型为 boolean

参数属性说明类型
array初始数组Array<unknown>
checkArray与初始数组做对比的数组Array<unknown>

arrayAllExistDeep

检测一个数组是否包含另一个数组中所有的值(深度对比)

查看代码
vue
<script setup lang="ts">
import { computed } from "vue";
import { arrayAllExistDeep } from "buzzts";

let arr1 = [
  123,
  [[[1, 2, 3]]],
  { nested: { a: 1, b: [1, 2, 3] } },
  [1, ["a", "b", "c"]],
  { key: "value" }
];
let arr2 = [
  [[[1, 2, 3]]],
  { nested: { a: 1, b: [1, 2, 3] } },
  [1, ["a", "b", "c"]]
];
let arr3 = [{ a: 1 }, 123];

function stringify(val) {
  return JSON.stringify(val);
}

let firstText = computed(() => {
  return `${stringify(arr1)} ${
    arrayAllExistDeep(arr1, arr2)
      ? "包含 " + stringify(arr2) + " 中所有的值"
      : "不包含 " + stringify(arr2) + " 中的所有值"
  }`;
});

let secondText = computed(() => {
  return `${stringify(arr1)} ${
    arrayAllExistDeep(arr1, arr3)
      ? "包含 " + stringify(arr3) + " 中所有的值"
      : "不包含 " + stringify(arr3) + " 中的所有值"
  }`;
});
</script>

<template>
  <naive-theme>
    <n-space vertical className="mt-2">
      <n-gradient-text type="info">
        {{ firstText }}
      </n-gradient-text>
      <n-gradient-text type="info">
        {{ secondText }}
      </n-gradient-text>
    </n-space>
  </naive-theme>
</template>

接收二个参数,第一个参数 array,第二个参数 checkArray,返回值类型为 boolean

参数属性说明类型
array初始数组Array<unknown>
checkArray与初始数组做对比的数组Array<unknown>

arrayAnyExist

检测一个数组是否包含另一个数组中任意一个值(内部使用new Set性能更好。该方法只针对基本数据类型,需要更复杂的场景可以用arrayAnyExistDeep

查看代码
vue
<script setup lang="ts">
import { computed } from "vue";
import { arrayAnyExist } from "buzzts";

let arr1 = [1, 4, 10];
let arr2 = [1, "3", 2];
let arr3 = [8, "9"];

function stringify(val) {
  return JSON.stringify(val);
}

let firstText = computed(() => {
  return `${stringify(arr1)} ${
    arrayAnyExist(arr1, arr2)
      ? "包含 " + stringify(arr2) + " 其中任意一个值"
      : "不包含 " + stringify(arr2) + " 其中任意一个值"
  }`;
});

let secondText = computed(() => {
  return `${stringify(arr1)} ${
    arrayAnyExist(arr1, arr3)
      ? "包含 " + stringify(arr3) + " 其中任意一个值"
      : "不包含 " + stringify(arr3) + " 其中任意一个值"
  }`;
});
</script>

<template>
  <naive-theme>
    <n-space vertical className="mt-2">
      <n-gradient-text type="info">
        {{ firstText }}
      </n-gradient-text>
      <n-gradient-text type="info">
        {{ secondText }}
      </n-gradient-text>
    </n-space>
  </naive-theme>
</template>

接收二个参数,第一个参数 array,第二个参数 checkArray,返回值类型为 boolean

参数属性说明类型
array初始数组Array<unknown>
checkArray与初始数组做对比的数组Array<unknown>

arrayAnyExistDeep

检测一个数组是否包含另一个数组中任意一个值(深度对比)

查看代码
vue
<script setup lang="ts">
import { computed } from "vue";
import { arrayAnyExistDeep } from "buzzts";

let arr1 = [
  123,
  [[[1, 2, 3]]],
  { nested: { a: 1, b: [1, 2, 3] } },
  [1, ["a", "b", "c"]],
  { key: "value" }
];
let arr2 = [
  [[[1, 2, 3]]],
  { nested: { a: 1, b: [1, 2, 3] } },
  [1, ["a", "b", "c"]]
];
let arr3 = [12, 456, [{ a: 1 }], [[22, 44]]];

function stringify(val) {
  return JSON.stringify(val);
}

let firstText = computed(() => {
  return `${stringify(arr1)} ${
    arrayAnyExistDeep(arr1, arr2)
      ? "包含 " + stringify(arr2) + " 其中任意一个值"
      : "不包含 " + stringify(arr2) + " 其中任意一个值"
  }`;
});

let secondText = computed(() => {
  return `${stringify(arr1)} ${
    arrayAnyExistDeep(arr1, arr3)
      ? "包含 " + stringify(arr3) + " 其中任意一个值"
      : "不包含 " + stringify(arr3) + " 其中任意一个值"
  }`;
});
</script>

<template>
  <naive-theme>
    <n-space vertical className="mt-2">
      <n-gradient-text type="info">
        {{ firstText }}
      </n-gradient-text>
      <n-gradient-text type="info">
        {{ secondText }}
      </n-gradient-text>
    </n-space>
  </naive-theme>
</template>

接收二个参数,第一个参数 array,第二个参数 checkArray,返回值类型为 boolean

参数属性说明类型
array初始数组Array<unknown>
checkArray与初始数组做对比的数组Array<unknown>

getBetween

通用区间遍历函数,支持数字、日期、字符等多种类型

通用区间遍历函数 getBetween - 多示例演示
查看代码
vue
<script setup lang="ts">
import { ref, computed, watch, onMounted } from "vue";
import { getBetween } from "buzzts";

type DemoItem = {
  label: string;
  start: any;
  end: any;
  step?: number;
  compare?: (current: any, end: any) => boolean;
  next: (current: any, step: number) => any;
};

function nextDate(current: Date, step: number): Date {
  const d = new Date(current);
  d.setDate(d.getDate() + step);
  return d;
}

function nextChar(c: string, step: number): string {
  return String.fromCharCode(c.charCodeAt(0) + step);
}

const demos: DemoItem[] = [
  {
    label: "数字区间 1 到 5",
    start: 1,
    end: 5,
    step: 1,
    next: (current, step) => current + step,
  },
  {
    label: "日期区间 2023-06-20 到 2023-06-23",
    start: new Date("2023-06-20T00:00:00"),
    end: new Date("2023-06-23T00:00:00"),
    step: 1,
    compare: (current, end) => current <= end,
    next: nextDate,
  },
  {
    label: "字符区间 'a' 到 'e'",
    start: "a",
    end: "e",
    step: 1,
    compare: (current, end) => current.charCodeAt(0) <= end.charCodeAt(0),
    next: nextChar,
  },
  {
    label: "无效输入(start=null)",
    start: null,
    end: 5,
    step: 1,
    next: (current, step) => current + step,
  },
];

const selectedIndex = ref(0);
const result = ref<any[] | null>(null);
const funcName = ref<string | null>(null);
const funcParams = ref<string | null>(null);

function runDemo(index: number) {
  selectedIndex.value = index;
  const demo = demos[index];
  funcName.value = demo.next.name; // 获取调用的函数名
  funcParams.value = `${demo.start},${demo.end},${demo.step}`; // 参数字符串

  try {
    result.value = getBetween(demo.start, demo.end, {
      step: demo.step,
      compare: demo.compare,
      next: demo.next,
    });
  } catch (e) {
    result.value = null;
  }
}

watch(selectedIndex, (newIndex) => {
  runDemo(newIndex);
});

onMounted(() => {
  runDemo(selectedIndex.value);
});

const resultText = computed(() => {
  return  `getBetween(${funcParams.value})= ${JSON.stringify(result.value)}\n`;
});

</script>

<template>
  <n-card title="通用区间遍历函数 getBetween - 多示例演示">
    <n-space vertical size="large">
      <n-space wrap>
        <n-button
          v-for="(item, index) in demos"
          :key="index"
          size="small"
          :type="selectedIndex === index ? 'primary' : 'default'"
          @click="runDemo(index)"
        >
          {{ item.label }}
        </n-button>
      </n-space>

      <n-gradient-text v-if="result !== null" type="info" style="margin-top: 12px;">
        {{ resultText }}
      </n-gradient-text>
    </n-space>
  </n-card>
</template>

参数属性说明类型默认值
start起点T
end终点T
options递增规则和比较规则{ step?: number; compare?: (current: T, end: T) => boolean; next: (current: T, step: number) => T; }
返回值说明
T[] | null包含起止的所有值数组,输入无效返回 null

  • 支持数字、日期、字符等区间遍历
  • 通过自定义比较和递增函数灵活控制遍历规则

mergeObject

深拷贝合并对象,优先使用 source 中的值覆盖 defaults

深拷贝合并对象 mergeObject - 多示例演示
mergeObject({ "a": 1 }, { "a": 0, "b": 2 }) = { "a": 1, "b": 2 }
查看代码
vue
<script setup lang="ts">
import { ref, computed } from "vue";
import { mergeObject } from "buzzts";

type DemoItem = {
  label: string;
  source: object | undefined;
  defaults: object | undefined;
};

const demos: DemoItem[] = [
  {
    label: "覆盖默认值",
    source: { a: 1 },
    defaults: { a: 0, b: 2 },
  },
  {
    label: "深度合并",
    source: { a: { x: 1 }, b: 2 },
    defaults: { a: { y: 2 }, c: 3 },
  },
  {
    label: "含 null 值跳过",
    source: { a: null, b: 2 },
    defaults: { a: 1, b: 0 },
  },
  {
    label: "空对象合并",
    source: {},
    defaults: { a: 1 },
  },
  {
    label: "非对象参数",
    source: null,
    defaults: undefined,
  },
  {
    label: "合并数组",
    source: { arr: [1, 2] },
    defaults: { arr: [3, 4], other: 5 },
  },
  {
    label: "合并嵌套对象",
    source: { a: { x: 1 }, b: 2 },
    defaults: { a: { y: 2, z: 3 }, b: 3 },
  },
  {
    label: "覆盖数组",
    source: { arr: [1, 2] },
    defaults: { arr: [3, 4], other: 5 },
  },
  {
    label: "处理布尔值",
    source: { isActive: true },
    defaults: { isActive: false, isAdmin: false },
  },
];

const selectedIndex = ref(0);
const result = ref<object>({});

function runDemo(index: number) {
  selectedIndex.value = index;
  const demo = demos[index];
  result.value = mergeObject(demo.source, demo.defaults);
}

runDemo(selectedIndex.value);

const resultText = computed(() => {
  const demo = demos[selectedIndex.value];
  const source = demo.source === null ? 'null' : JSON.stringify(demo.source, null, 2);
  const defaults = demo.defaults === null ? 'null' : JSON.stringify(demo.defaults, null, 2);
  return `mergeObject(${source}, ${defaults}) = ${JSON.stringify(result.value, null, 2)}`;
});
</script>

<template>
  <n-card title="深拷贝合并对象 mergeObject - 多示例演示">
    <n-space vertical size="large">
      <n-space wrap>
        <n-button
          v-for="(item, index) in demos"
          :key="index"
          size="small"
          :type="selectedIndex === index ? 'primary' : 'default'"
          @click="runDemo(index)"
        >
          {{ item.label }}
        </n-button>
      </n-space>

      <n-gradient-text v-if="result !== null" type="info" style="margin-top: 12px;">
        {{ resultText }}
      </n-gradient-text>
    </n-space>
  </n-card>
</template>

参数属性说明类型默认值
source外部的参数对象object?
defaults默认参数对象object?
返回值说明
object合并后的新对象

  • 深拷贝合并对象,递归合并普通对象
  • 跳过 null 值,防止原型污染

deepClone

深度复制对象,支持循环引用、日期、正则、原型链和属性描述符

深度复制对象 deepClone - 多示例演示
deepClone({ "a": 1, "b": 2 }) = { "a": 1, "b": 2 }
查看代码
vue
<script setup lang="ts">
import { ref, computed } from "vue";
import { deepClone } from "buzzts";

type DemoItem = {
  label: string;
  obj: any;
};

const demos: DemoItem[] = [
  {
    label: "简单对象",
    obj: { a: 1, b: 2 },
  },
  {
    label: "嵌套对象",
    obj: { a: { x: 1 }, b: [1, 2, 3] },
  },
  {
    label: "日期和正则",
    obj: { date: new Date("2023-06-01"), reg: /test/i },
  },
];

const selectedIndex = ref(0);
const cloned = ref<any>(null);

function runDemo(index: number) {
  selectedIndex.value = index;
  const demo = demos[index];
  cloned.value = deepClone(demo.obj);
}

runDemo(selectedIndex.value);

function safeStringify(obj: any): string {
  try {
    return JSON.stringify(obj, null, 2);
  } catch {
    return String(obj);
  }
}

const resultText = computed(() => {
  const demo = demos[selectedIndex.value];
  const objStr = demo.obj === null ? 'null' : safeStringify(demo.obj);
  const clonedStr = safeStringify(cloned.value);
  return `deepClone(${objStr}) = ${clonedStr}`;
});

</script>

<template>
  <n-card title="深度复制对象 deepClone - 多示例演示">
    <n-space vertical size="large">
      <n-space wrap>
        <n-button
          v-for="(item, index) in demos"
          :key="index"
          size="small"
          :type="selectedIndex === index ? 'primary' : 'default'"
          @click="runDemo(index)"
        >
          {{ item.label }}
        </n-button>
      </n-space>
      
      <n-gradient-text v-if="result !== null" type="info" style="margin-top: 12px;">
        {{ resultText }}
      </n-gradient-text>
    </n-space>
  </n-card>
</template>

参数属性说明类型默认值
obj将要复制的对象T
hash用于处理循环引用的哈希表WeakMap<any, any>?新建 WeakMap
返回值说明
T复制后的对象

  • 支持各种复杂类型的深度复制
  • 处理循环引用,保证复制安全

chunkArray

将数组分成指定数量的块(尽量平均分配)

chunkArray - 数组分块演示
请设置数组和分块数
查看代码
vue
<script setup lang="ts">
import { ref, computed, watch, onMounted } from "vue";
import { chunkArray } from "buzzts";

type DemoItem = { label: string; value: number[]; chunkCount: number };

const demos: DemoItem[] = [
  { label: "10个数字分2块", value: [1,2,3,4,5,6,7,8,9,10], chunkCount: 2 },
  { label: "10个数字分3块", value: [1,2,3,4,5,6,7,8,9,10], chunkCount: 3 },
  { label: "5个数字分10块(块数大于长度)", value: [1,2,3,4,5], chunkCount: 10 },
  { label: "空数组分1块", value: [], chunkCount: 1 },
];

const selectedIndex = ref(0);
const val = ref(demos[0].value);
const chunkCount = ref(demos[0].chunkCount);
const result = ref<number[][] | string | null>(null);
const errorMsg = ref<string>("");

function tryChunkArray() {
  errorMsg.value = "";
  try {
    result.value = chunkArray(val.value, chunkCount.value);
  } catch (error: any) {
    result.value = null;
    errorMsg.value = error.message || "未知错误";
  }
}

function selectDemo(index: number) {
  selectedIndex.value = index;
  val.value = demos[index].value;
  chunkCount.value = demos[index].chunkCount;
  tryChunkArray();
}

watch([val, chunkCount], () => {
  tryChunkArray();
});

onMounted(() => {
  tryChunkArray();
});

const resultText = computed(() => {
  if (errorMsg.value) return `错误: ${errorMsg.value}`;
  if (result.value === null) return "请设置数组和分块数";
  return JSON.stringify(result.value);
});
</script>

<template>
  <n-card title="chunkArray - 数组分块演示">
    <n-space vertical size="large">
      <n-space wrap>
        <n-button
          v-for="(item, index) in demos"
          :key="index"
          size="small"
          :type="selectedIndex === index ? 'primary' : 'default'"
          @click="selectDemo(index)"
        >
          {{ item.label }}
        </n-button>
      </n-space>

      <n-input
        v-model:value="val"
        placeholder="请输入数组,逗号分隔"
        @change="val = val.split(',').map(v => Number(v.trim())).filter(v => !isNaN(v))"
      />

      <n-input-number
        v-model:value="chunkCount"
        placeholder="分块数"
        :min="1"
        :max="val.length"
      />

      <n-button type="primary" @click="tryChunkArray">分块</n-button>

      <n-text style="margin-top: 12px;" type="error" v-if="errorMsg">{{ errorMsg }}</n-text>
      <n-text style="margin-top: 12px;" v-else>{{ resultText }}</n-text>
    </n-space>
  </n-card>
</template>

参数属性说明类型默认值
data要分块的数组T[]
chunkCount分块数量,正整数且不超过数组长度number
返回值说明
T[][]分块后的二维数组

  • 将数组分成指定数量的块,尽量平均分配元素
  • 如果分块数大于数组长度,每个元素单独成块
  • 参数校验失败时会抛错

Released under the MIT License