这篇文章上次修改于 1111 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

大家都在写博文,最怕的就是博文内容没有成功保存了。那么有什么办法可以减少遇到这样的情况呢?自然就是想办法让「窗口」不能被关掉呀。

那么问题来了,有什么方法可以拦截呢?这个问题我寻找了很久很久,才得知 Window 有一个叫做 onbeforeunload 的事件。

这个事件的编写方式,大概长这样:

window.addEventListener("beforeunload", function (ev){
  ev.preventDefault();
  ev.returnValue = '是否保存?';
});

但它只适合普通页面,并不适用于 React 编写的网页,我的写法是加在 componentDidMount 初始化,componentWillUnmount 清除这个 Event,但是我发现这样写的话,只要 Unmount 就去除了 Event,根本就不会弹窗询问。

这很有可能是压根无法触发此事件,所以我在寻找着 React 下的写法,一番搜索过后,我终于找到了答案。

食用方法

首先引入 Prompt 组件,然后在你的 render 里面编写以下内容:

import {Prompt} from "react-router-dom";
<Prompt
  when={hasModified}
  message="修改还没保存,确定离开吗?"
/>

PS:此处的 hasModified 是一个 State,需要自己指定。在我代码里面的用途,是指修改过日记里的内容。

来源于官方文档

分析

通过浏览器开发工具,可以看出 React-Router-DOM 的写法,并非使用了 window.onbeforeunload 这个事件,毕竟它的前进后退都是通过修改 History 实现的。我的猜测就是在切换页面前,使用了 window.prompt 拦截(所以可以显示自定义的内容),根据选中的按钮,来决定是否改变页面内容并修改 History。

为什么我这么肯定呢?因为当我尝试直接「刷新/关闭」我上面 React-Router-DOM 写的那个网页,会完全没有效果。只有前进后退才有!

总的来说,这还是没能完美解决页面容易被关闭的问题(非 React 的话效果还是很不错的),还是老老实实养成多多保存的习惯吧!