Files
kefu/admin-web/apps/mobile-h5/src/composables.ts
T
2026-09-29 15:52:07 +08:00

75 lines
2.3 KiB
TypeScript

import { onActivated, onBeforeUnmount, onDeactivated, onMounted, ref } from 'vue';
/** ≥768px(平板横竖屏、桌面浏览器)切成左右两栏。 */
export function useWide(query = '(min-width: 768px)') {
const media = typeof window !== 'undefined' && window.matchMedia ? window.matchMedia(query) : null;
const wide = ref(media ? media.matches : false);
const update = (event: MediaQueryListEvent) => {
wide.value = event.matches;
};
onMounted(() => media?.addEventListener?.('change', update));
onBeforeUnmount(() => media?.removeEventListener?.('change', update));
return wide;
}
export function usePrefersDark() {
const media =
typeof window !== 'undefined' && window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
const dark = ref(media ? media.matches : false);
const update = (event: MediaQueryListEvent) => {
dark.value = event.matches;
};
onMounted(() => media?.addEventListener?.('change', update));
onBeforeUnmount(() => media?.removeEventListener?.('change', update));
return dark;
}
/**
* 页面可见时按间隔刷新;切到后台就停,回到前台立刻补一次。
* 手机锁屏后还在轮询只会白白耗电和流量。被 KeepAlive 缓存的页面切走时也停。
*/
export function useVisibleInterval(task: () => unknown, intervalMs: number) {
let timer: number | undefined;
let active = false;
const stop = () => {
if (timer !== undefined) window.clearInterval(timer);
timer = undefined;
};
const start = () => {
stop();
timer = window.setInterval(() => {
if (document.visibilityState === 'visible') void task();
}, intervalMs);
};
const onVisibility = () => {
if (!active) return;
if (document.visibilityState === 'visible') {
void task();
start();
} else {
stop();
}
};
onMounted(() => {
active = true;
start();
document.addEventListener('visibilitychange', onVisibility);
});
onActivated(() => {
// 首次挂载也会触发 activated;那一次 onMounted 已经启动过了。
if (active) return;
active = true;
void task();
start();
});
onDeactivated(() => {
active = false;
stop();
});
onBeforeUnmount(() => {
active = false;
stop();
document.removeEventListener('visibilitychange', onVisibility);
});
}