75 lines
2.3 KiB
TypeScript
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);
|
|
});
|
|
}
|