React单页应用中使用react-router-v4自定义页面离开确认弹框的方法

栏目: 服务器 · 发布时间: 4年前

内容简介:项目技术栈是react+ant-design;产品需求是在某个页面表单有信息输入或变更,用户未保存要离开该页面时,自定义提示用户提示,如果用户确认离开则跳转到新页面,否则留在当前页。在react单页应用中,需要根据用户的选择来是否跳转页面,也就是需要阻塞浏览器的页面跳转,类似

项目技术栈是react+ant-design;

产品需求是在某个页面表单有信息输入或变更,用户未保存要离开该页面时,自定义提示用户提示,如果用户确认离开则跳转到新页面,否则留在当前页。

React单页应用中使用react-router-v4自定义页面离开确认弹框的方法

思考

在react单页应用中,需要根据用户的选择来是否跳转页面,也就是需要阻塞浏览器的页面跳转,类似 标签点击后的return false效果,待到用户操作后再执行后续操作。

首先,能想到的是浏览器的window.confirm方法,在交互上完全符合需求,那么自定义需求呢?经过查阅资料发现,目前主流浏览器都不支持该方法样式的自定义,因此放弃。

其次,就是react的方案,react中,控制页面路由的是react-router,若官方提供了这种能力便是更好的。于是,我查阅了其官方文档: react-guide.github.io/react-route… 、或者 reacttraining.com/react-route… 、中文版 segmentfault.com/a/119000001…

关键文档

由于项目中使用的是react-router-v4,所以直接查看最新的API(如果是较老版本有比较简单的实现,可参考 blog.csdn.net/ISaiSai/art…

一、Prompt组件

import { Prompt } from 'react-router-dom';
....
render(){
  return(
      <Prompt message="确定要离开?"  when={true}/>
  )
}
复制代码

如上代码,可以使用react-router-dom的Prompt,在JSX的任意render方法中(不仅仅是在router组件中)都可以使用,使用后当前页面组件离开就会给用户提示信息,默认弹框为浏览器的window.confirm弹框。

  1. message: string 当用户离开当前页面时,设置的提示信息。
  2. message: func 当用户离开当前页面时,设置的回掉函数,返回 true 时允许直接跳转 <Prompt message={location => ( Are you sue you want to go to ${location.pathname}? )} />
  3. when: bool 通过设置一定条件要决定是否启用 Prompt,属性值为true时启用防止转换;

二、Router组件的getUserConfirmation方法

用于确认导航的函数,默认使用window.confirm。例如,当从  /a 导航至  /b 时,会使用默认的  confirm 函数弹出一个提示,用户点击确定后才进行导航,否则不做任何处理。需要配合  <Prompt> 一起使用。

const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message);
  callback(allowTransition);
}

<BrowserRouter getUserConfirmation={getConfirmation} />
复制代码

实现方案

中心思想:阻塞页面,等待用户操作后异步处理页面跳转(router变更)。

探索一:Prompt既然是组件,那么在组件内使用state变更的方式去render是否可行?

尝试如下代码:

...
<Prompt
   message = {(location)=>{
     return this.state.customPromt,
     }
   }
  />
...
复制代码

实践证明这是不行的,prompt组件的message方法被同步调用了,不能达到阻塞页面跳转的效果。

探索二:尝试async/await

既然是要异步执行,那么就可以尝试async/await的异步处理方式,同步写。恰好message也可以是一个function。于是,新的尝试代码如下:

...
handlePrompt = async () => {
	const leaveConfirm = new Promise((res, rej) => {
		confirm({
			content: 'Are you sure?',
			onOk() {
				res(true);
			},
			onCancel() {
				res(false);
			},
		});
	});

	const leave = await leaveConfirm;
	return leave ;
}
...
<Prompt message={(location) => {this.handlePrompt} />
...
复制代码

满怀期待,然后...还是不行。仔细查阅文档发现,message方法返回的是一个字符串或者true,返回字符串则调用浏览器默认的prompt方法阻塞页面跳转,和直接使用window.prompt同效果,不符合需求;返回true则直接跳转。

message: func

Will be called with the next location and  action the user is attempting to navigate to. Return a string to show a prompt to the user or  true to allow the transition.

以上尝试代码,虽然添加了异步方法,也会执行异步函数,但是始终会跳转页面,经查原因为: github.com/ReactTraini…

探索三:getUserConfirmation方法, github.com/ReactTraini…

前两种方案都失败了,那么再次阅读文档发现,getUserConfirmation方法就是提供给我们自定义用的,默认情况下,当页面使用了prompt组件后,调用的getUserConfirmation方法是浏览器默认的window.prompt。如果需要自定义,直接覆盖即可。

简单示例代码如下:

const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message);
  callback(allowTransition);
}

<BrowserRouter getUserConfirmation={getConfirmation} />
复制代码

ps: 注意该方法需要写在BrowserRouter 或 MemoryRouter 上。

那么接下来的问题,就是将自定义的或者其他UI组件融合到该方法内。 已实现的代码如下:

import { Modal } from 'antd';
...
function getConfirmation(message, callback) { // 至关重要的callback方法,可以异步执行
	if (!G.pageChangeConfirm) { // G.pageChangeConfirm为页面内的全局变量,用于数据交互与条件判断
		callback(true);
		return;
	}
	Modal.confirm({
		title: '离开该页面,表单信息将不被保留?是否确定离开该页面?',
		content: '',
		okText: '离开',
		cancelText: '取消',
		onOk() {
			callback(true);
		},
		onCancel() {
			callback(false);
		},
	});
}

ReactDOM.render((
	<BrowserRouter
		getUserConfirmation={getConfirmation}
	>
		<App />
	</BrowserRouter>
	, document.getElementById('react-wraper')
);
...
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Practical Django Projects, Second Edition

Practical Django Projects, Second Edition

James Bennett / Apress / 2009 / 44.99

Build a django content management system, blog, and social networking site with James Bennett as he introduces version 1.1 of the popular Django framework. You’ll work through the development of ea......一起来看看 《Practical Django Projects, Second Edition》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具