53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
import { useEffect } from 'react';
|
||
import { FormInstance } from 'antd';
|
||
|
||
interface UseFormGuardOptions {
|
||
form: FormInstance;
|
||
enabled?: boolean;
|
||
onSaveDraft?: () => void;
|
||
}
|
||
|
||
/**
|
||
* 表单离开拦截 Hook
|
||
* - 浏览器刷新/关闭拦截 (beforeunload)
|
||
* - 移动端切后台时保存草稿 (visibilitychange + pagehide)
|
||
*
|
||
* 注意:路由跳转拦截需要在使用组件中手动处理(因为 BrowserRouter 不支持 useBlocker)
|
||
*/
|
||
function useFormGuard(options: UseFormGuardOptions) {
|
||
const { form, enabled = true, onSaveDraft } = options;
|
||
|
||
// 浏览器刷新/关闭拦截
|
||
useEffect(() => {
|
||
if (!enabled) return;
|
||
const handler = (e: BeforeUnloadEvent) => {
|
||
if (form.isFieldsTouched()) {
|
||
e.preventDefault();
|
||
}
|
||
};
|
||
window.addEventListener('beforeunload', handler);
|
||
return () => window.removeEventListener('beforeunload', handler);
|
||
}, [form, enabled]);
|
||
|
||
// 移动端:页面切到后台时保存草稿
|
||
useEffect(() => {
|
||
if (!enabled || !onSaveDraft) return;
|
||
const handler = () => {
|
||
if (document.visibilityState === 'hidden' && form.isFieldsTouched()) {
|
||
onSaveDraft();
|
||
}
|
||
};
|
||
document.addEventListener('visibilitychange', handler);
|
||
const pageHideHandler = () => {
|
||
if (form.isFieldsTouched()) onSaveDraft();
|
||
};
|
||
window.addEventListener('pagehide', pageHideHandler);
|
||
return () => {
|
||
document.removeEventListener('visibilitychange', handler);
|
||
window.removeEventListener('pagehide', pageHideHandler);
|
||
};
|
||
}, [form, enabled, onSaveDraft]);
|
||
}
|
||
|
||
export default useFormGuard;
|