React 系统中,在离开编辑页面前做提示
汉朝老贼
这个人很懒,什么也没留下。
3 人赞同了该文章
在做有编辑器相关需求的时候,遇到一个之前没遇到过的需求:用户离开当前页面前,需要提示用户保存。
由于是用 react 开发的单页应用,涉及到离开当前页面的场景会有: 1. 用户系统内跳转到其他路由 2. 用户点击浏览器上的刷新、关闭浏览器标签页等操作
下面分开解决以上问题。
路由跳转
路由跳转会导致组件卸载,我们自然而然会想到在 react 组件的 componentWillUnmount
生命周期中做一些提示,但是使用这个方法会有个问题:这里并没有办法阻止路由的跳转,这个过程是不可终止的,所以并不能满足需求。
我最开始的想法是在 react 生态中寻找类似于 Vue Router 的 导航守卫 来实现对路由跳转的拦截
beforeRouteLeave (to, from , next) { const answer = window.confirm('Do you really want to leave? you have unsaved changes!') if (answer) { next() } else { next(false) } }
这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
而在 react-router 之前的版本也是存在路由守卫的,但是很遗憾,react-router-dom v4 去除了相关 api,但是我们可以通过其提供的 <Prompt/>
组件来实现。
import {Prompt} from 'react-router-dom'; // 只需把这个组件放在页面中,即可实现路由跳转前的拦截提示 <div> <Prompt when={true} message={() => '离开当前页后,所编辑的数据将不可恢复'} /> </div>
when
可以动态改变是否需要提示message
为提示消息
这样,只要是跳转到其他路由都会触发这个提示。
效果如图:
浏览器级刷新或者关闭页面
当浏览器窗口关闭或者刷新时,会触发 beforeunload 事件。当前页面不会直接关闭,可以点击确定按钮关闭或刷新,也可以取消关闭或刷新。
如果处理函数为 Event
对象的 returnValue
属性赋值非空字符串,浏览器会弹出一个对话框,来询问用户是否确定要离开当前页面。有些浏览器会将返回的字符串展示在弹框里,但有些其他浏览器只展示它们自定义的信息。没有赋值时,该事件不做任何响应。
我们只需在页面组件上绑定该事件,即可完成该功能。
const listener = e => { e.preventDefault(); e.returnValue = '离开当前页后,所编辑的数据将不可恢复' // 浏览器有可能不会提示这个信息,会按照固定信息提示 } // ... componentDidMount() { window.addEventListener('beforeunload', listener) }, componentWillUnmount() { window.removeEventListener('beforeunload', listener) } // ....
效果如图:
最后,我们可以把这两部分逻辑抽象起来,形成一个需要具有该特定功能的组件,不过这部分就不贴出来了,与主题相关度不足。