@fallen-zero/use

fallen-zero Api
2,609 2
Install
npm install @fallen-zero/use
Latest Version:1.3.5
Vue:3
License:MIT
Last Updated:Feb 5, 2026
Links: GitHub  ·  npm
Maintainer: fallen-zero

Fallen-Zero Use

Vue 3 composition hooks and browser utilities used by Fallen Zero projects.

Install

# with npm
npm i @fallen-zero/use

# with yarn
yarn add @fallen-zero/use

# with pnpm
pnpm add @fallen-zero/use

Usage

import { useRequest, useVisible } from '@fallen-zero/use';

功能

请求与列表

API 说明
useRequest 包装 Promise 请求,返回 data、error、loading、run、setParams、reset、cancel。
useRequestImmediate 立即执行一次请求并返回响应式状态。
useApiList 分页列表加载,提供 list、total、loading、finished、onLoad、reset。

Vue Hooks

API 说明
useVisible 管理弹窗、抽屉等布尔显示状态。
useDebounceRef 创建带防抖写入的 ref。
UseDefer 按动画帧延迟渲染大量内容。
useCompRef / useCompRefs 为组件实例创建带类型的 ref。
useIntervalDate 每秒更新当前日期、时间和星期。
useCountdown 根据结束时间生成 HH:mm:ss 倒计时。
useTimeDown 基于 localStorage 的验证码/冷却倒计时。
useTheme 管理 light / dark 主题并写入 data-theme。
useResize 复用单个 ResizeObserver 监听元素尺寸变化。
useRem 根据设计稿宽度设置根元素 font-size。
useLoopExec 按固定间隔循环执行同步或异步任务。
useAnimation 使用 requestAnimationFrame 生成补间动画值。
useStore / StorageEnum 统一读写 sessionStorage、localStorage 和 Cookie。

工具函数

API 说明
dateFormat / DATE_FORMAT 常用日期格式化。
decimalPlaces / toFixed / toPrecision / sum 数字精度和求和工具。
strToArray / arrayToStr / parseJSON 字符串、数组和 JSON 转换。
encryptName / encrypt 姓名、手机号、身份证、银行卡、邮箱脱敏。
getSystemAgent / UserAgent 判断 iOS、Android、微信、钉钉等运行环境。
FontSize 根据屏幕宽度计算适配后的字体大小。
useFormData 将对象转换为 FormData。
ImageCompression、base64ToBlob、base64ToFile、fileToBinary 图片压缩和文件转换。
getFileExt / getFileSize / getFileName / useFullUrl 文件名、大小和 URL 处理。
numToCapital / toChineseAmount 数字转中文或人民币大写。
getIdCardInfo / getAgeByIdCard / getSexByIdCard 根据身份证号获取年龄和性别。
isEmptyValue / isImage / isVideo 空值、图片路径和视频路径判断。
validatePhone / validateTel / validatePhoneAndTel 手机号和电话号码校验。
validatePhoneAndTelMD / isVehicleNumber 脱敏号码和车牌号校验。
anyIsEqual / arrayIsEqual / objectIsEqual / isAllEqual 深比较数组、对象和值。
convertColor 将 hex/rgb/rgba 转为带透明度的 rgba。
createField / fommaterIndex 生成展示字段配置。
Loader 动态挂载和卸载 Vue 组件。
createTagMsg 基于 BroadcastChannel 的跨标签页消息。
preformChunk / browserPerformChunk / timeoutPerformChunk 分片执行大批量任务,避免长时间阻塞主线程。
isFunction、isObject、isArray 等 常用类型判断函数。

使用案例

请求与列表

import {
  CreateRequest,
  useApiList,
  useRequest,
  useRequestImmediate,
} from '@fallen-zero/use';

const getUser = (id: number) => Promise.resolve({ id, name: 'Zero' });

const request = useRequest(getUser, [1], {
  immediate: false,
  success: (user) => console.log(user.name),
});

await request.run();
await request.setParams([2]);
await request.reset();
request.cancel();

const appRequest = new CreateRequest({
  checkStatus: (res) => res.code === 0,
  showError: (err) => console.error(err),
});

const userRequest = appRequest.requestApi(
  () => Promise.resolve({ code: 0, data: [] }),
  [],
  { immediate: false },
);
await userRequest.run();

const immediate = await useRequestImmediate(getUser, 1);
console.log(immediate.data.value);

const listApi = ({ page = 1, limit = 10 }) =>
  Promise.resolve({
    list: Array.from({ length: limit }, (_, index) => page * limit + index),
    total: 100,
  });

const { list, total, loading, finished, onLoad, reset, setParams } = useApiList(
  listApi,
  { page: 1, limit: 20 },
  { immediate: false },
);

await onLoad();
await setParams({ limit: 30 });
await reset();
console.log(list.value, total.value, loading.value, finished.value);

Vue Hooks

import {
  StorageEnum,
  UseDefer,
  useAnimation,
  useCompRef,
  useCompRefs,
  useCountdown,
  useDebounceRef,
  useIntervalDate,
  useLoopExec,
  useRem,
  useResize,
  useStore,
  useTheme,
  useTimeDown,
  useVisible,
} from '@fallen-zero/use';
import UserCard from './UserCard.vue';

const modal = useVisible();
modal.open();
modal.toggle();
modal.close();
console.log(modal.visible.value);

const keyword = useDebounceRef('', 300);
keyword.value = 'search text';

const defer = new UseDefer(60);
const showRow = defer.defer(20);
defer.setMaxCount(120);
console.log(showRow, defer.getMaxCount());

const userCardRef = useCompRef(UserCard);
const userCardRefs = useCompRefs(UserCard);

const { currDate } = useIntervalDate();
console.log(currDate.date, currDate.time, currDate.week);

const countdown = useCountdown('2026-12-31 23:59:59');
console.log(countdown.currentTime.value, countdown.isEnd.value);
countdown.clearTimer();
countdown.startTimer();

const verifyCode = useTimeDown('login-code', 60, () => console.log('done'));
verifyCode.start();
console.log(verifyCode.time.value, verifyCode.finish.value);
verifyCode.stop();

const { theme, toggleTheme } = useTheme('light');
toggleTheme('dark');
console.log(theme.value);

const { observe, unobserve } = useResize();
const element = document.querySelector('#panel');
observe(element, () => console.log('resized'));
unobserve(element);

const { changeRem } = useRem({ designWidth: 1920, size: 192 });
changeRem({ rootWidth: 1440 });

const loop = useLoopExec(() => console.log(Date.now()), 2000);
loop.loop();
loop.cancel();

useAnimation(300, 0, 100, (value) => {
  document.body.style.opacity = String(value / 100);
});

const store = useStore('demo');
store.set('token', 'abc', { storage: StorageEnum.LOCAL, expire: 3600 });
console.log(store.get<string>('token', StorageEnum.LOCAL));
store.remove('token', StorageEnum.LOCAL);

日期、数字与字符串

import {
  DATE_FORMAT,
  arrayToStr,
  dateFormat,
  decimalPlaces,
  fommaterIndex,
  numToCapital,
  parseJSON,
  strToArray,
  sum,
  toChineseAmount,
  toFixed,
  toPrecision,
} from '@fallen-zero/use';

dateFormat(new Date(), DATE_FORMAT['DATETIMES-']);
decimalPlaces(3.1415);
toFixed(3.1415, 2);
toPrecision(3.1415, 2);
sum(1, 2, 3);

strToArray('a,b,c');
arrayToStr(['a', 'b', 'c']);
parseJSON('{"name":"Zero"}', { name: '' });

numToCapital(1203);
toChineseAmount(1203.45);
fommaterIndex(8);

文件与浏览器工具

import {
  FontSize,
  ImageCompression,
  UserAgent,
  base64ToBlob,
  base64ToFile,
  convertColor,
  createTagMsg,
  fileToBinary,
  getFileExt,
  getFileName,
  getFileSize,
  getSystemAgent,
  useFormData,
  useFullUrl,
} from '@fallen-zero/use';

declare const file: File;
declare const base64: string;

const formData = useFormData({ name: 'Zero', tags: ['vue'] });

new ImageCompression({
  file,
  quality: 0.8,
  success: (base64) => console.log(base64),
});

const blob = base64ToBlob(base64, 'image/png');
const imageFile = base64ToFile(base64, 'avatar.png', 'image/png');
const bytes = await fileToBinary(imageFile);

getFileExt('avatar.png');
getFileSize(file);
getFileName('/upload/avatar.png');
const fullUrl = useFullUrl('https://cdn.example.com');
fullUrl('~/avatar.png');

FontSize(16);
getSystemAgent(UserAgent.微信);
convertColor('#1677ff', 0.5);

const tagMsg = createTagMsg('app');
const stopListen = tagMsg.listenMsg((msg) => console.log(msg.type));
tagMsg.sendMsg('refresh', { id: 1 });
stopListen();

校验、比较与类型判断

import {
  anyIsEqual,
  arrayIsEqual,
  encrypt,
  encryptName,
  getAgeByIdCard,
  getIdCardInfo,
  getSexByIdCard,
  isAllEqual,
  isArray,
  isBoolean,
  isDate,
  isEmptyValue,
  isFile,
  isFunction,
  isImage,
  isNull,
  isNumber,
  isObject,
  isPromise,
  isRegExp,
  isString,
  isUndefined,
  isVehicleNumber,
  isVideo,
  objectIsEqual,
  validatePhone,
  validatePhoneAndTel,
  validatePhoneAndTelMD,
  validateTel,
} from '@fallen-zero/use';

declare const file: File;

encryptName('张三');
encrypt('phone', '13800138000');

getSexByIdCard('110101199001011234');
getAgeByIdCard('110101199001011234');
getIdCardInfo('110101199001011234');

isEmptyValue('');
isImage('avatar.webp');
isVideo('demo.mp4');
isVehicleNumber('浙A12345');
validatePhone('13800138000');
validateTel('0571-12345678');
validatePhoneAndTel('0571-12345678');
validatePhoneAndTelMD('138****8000');

isAllEqual({ a: 1 }, { a: 1 });
arrayIsEqual([1, 2], [2, 1], true);
objectIsEqual({ a: 1 }, { a: 1 });
anyIsEqual([{ a: 1 }], [{ a: 1 }]);

isFunction(() => {});
isObject({});
isArray([]);
isString('zero');
isNumber(1);
isBoolean(false);
isDate(new Date());
isRegExp(/zero/);
isUndefined(undefined);
isNull(null);
isPromise(Promise.resolve());
isFile(file);

字段、加载器与分片任务

import {
  Loader,
  browserPerformChunk,
  createField,
  preformChunk,
  timeoutPerformChunk,
} from '@fallen-zero/use';
import Toast from './Toast.vue';

const fields = createField(
  [
    { label: '姓名', key: 'name' },
    { label: '年龄', key: 'age', visible: (age) => age > 0 },
  ],
  { name: 'Zero', age: 18 },
);

const loader = new Loader(Toast);
await loader.show();
loader.hide();

browserPerformChunk([1, 2, 3], (item) => console.log(item));
timeoutPerformChunk(1000, (_, index) => console.log(index), 16, 0);

preformChunk(
  [1, 2, 3],
  (item) => console.log(item),
  (task) => task(() => true),
);

console.log(fields);

Related Packages

@vueuse/sound

🔊 A Vue composable for playing sound effects

847,884 559
@raffaelesgarro/vue-use-sound

🔊 A Vue composable for playing sound effects

39,051 559
vue-use-vuex

Fixed: must call Vue.use(Vuex) before creating a store instance.

1,831 2
@uni-helper/uni-use

uni-app (vue3) 组合式工具集

25,772 182
nuxt-use-motion

🤹 A Nuxt module putting your components in motion

2,812

Version History

Version Released Vue License
1.3.5 ^3.0.0 MIT
1.3.4 ^3.0.0 MIT
1.3.3 ^3.0.0 MIT
1.3.2 ^3.0.0 MIT
1.3.1 ^3.0.0 MIT