react router页面跳转二次确认弹框及样式、业务逻辑自定义
react router页面跳转二次确认弹框及样式、业务逻辑自定义
我们在编辑页面时如果需要跳走通常会需要给用户提示,react router本身已经给了我们这样的功能,我们先看看怎么使用。
初见二次确认弹框
// App.jsx
const App = () {
return (
<BrowserRouter>
<div>
<ul style={{marginTop: '10px'}}>
<li>
<Link to='/'>Home</Link>
</li>
<li>
<Link to='/write'>Write</Link>
</li>
</ul>
<Switch>
<Route exact path='/'>
</Route>
<Route path='/write' strict={true} forceRefresh={true} component={WriteMail}>
</Route>
</Switch>
</div>
</BrowserRouter>
);
}
export default App;
在WriteMail组件里面我们加上Prompt
组件并且设置when
为true
,就会有二次确认弹框了,也就是从/write
页面跳转时会需要进行确认
// WriteMail.jsx
const WriteMail = () => {
function redirectMsg(location, type) {
return type + ': Go to ' + location.pathname;
}
return (
<div>
<h1>Write</h1>
<Prompt when={true} message={(a) => redirectMsg(a, '外层')}></Prompt>
</div>
);
};
export default WriteMail;
效果如下
自定义二次确认弹框
功能是有了,但是界面也太丑了吧。不用担心,react router当然支持自定义二次弹框啊。
我们的二次确认弹框其实通过给BrowserRouter
(或者HashRouter
)组件设置属性来自定义的,它默认的就是window.confirm
官方是这么说的
<BrowserRouter
getUserConfirmation={(message, callback) => {
// this is the default behavior
const allowTransition = window.confirm(message);
callback(allowTransition);
}}
>
</BrowserRouter>
所以我们需要修改下App.jsx了,我们这里引入antd的Modal
做弹框
// App.jsx
const App = () {
const getUserConfirmation = (message, callback) => {
Modal.confirm({
title: '提示',
content: '您即将放弃编辑邮件,是否需要将当前内容保存为草稿?',
cancelText: '不保存',
okText: '保存草稿',
onCancel: () => {
callback(false);
},
onOk: () => {
callback(true);
}
});
}
return (
<BrowseRrouter>
<div>
<ul style={{marginTop: '10px'}}>
<li>
<link to='/'/>Home
</li>
<li>
<link to='/write'/>Write
</li>
</ul>
<Switch>
<Route exact path='/'>
</Route>
<Route path='/write' strict={true} forceRefresh={true} component={WriteMail}>
</Route>
</Switch>
</div>
</BrowseRrouter>
);
}
export default App;
是不是很完美?
进阶
这个getUserConfirmation
属性是在BrowserRouter
组件上的,一般我们的项目可能只在组件树的外层才会有一层BrowserRouter
,而业务组件一般是在其里面的Route
组件的里面,即
<BrowseRrouter getUserConfirmation={getUserConfirmation}>
<Switch>
<Route>
<WriteMail></WriteMail>
</Route>
</Switch>
</BrowseRrouter>
如果我们需要在getUserConfirmation
里面出来当前WriteMail
相应的业务逻辑怎么弄?(比如弹框提示文案是“您即将跳转,是否需要保存草稿?”,我们需要执行WriteMail
里面的保存草稿逻辑。)
我们很容易想到,如果能将Router
组件,放到WriteMail
里面就好了,那样我们就能将getUserConfirmation
写在WriteMail
,执行对应的逻辑就很容易了。
我们尝试下在WriteMail
加一层BrowserRouter
,同时需要将业务逻辑(编辑组件)放置于内层的Route
下,即多了一层路由
// WriteMail.jsx
function WriteMail(props) {
const [value, setValue] = useState('');
const getUserConfirmationInWrite = (message, callback) => {
Modal.confirm({
title: message,
onCancel: () => {
callback(false);
},
onOk: () => {
callback(true);
}
});
}
return (
<div>
<h1>Write</h1>
<Prompt when={true} message={(a) => redirectMsg(a, '外层')}></Prompt>
<ul style={{marginTop: '10px'}}>
<li>
<link to='/write/first'/>First
</li>
<li>
<link to='/write/second'/>Second
</li>
</ul>
<BrowserRouter getUserConfirmation={getUserConfirmationInWrite}>
<Route path='/write/first'>
<h3>first</h3>
<Prompt when={true} message={(a) => redirectMsg(a, '内层')}></Prompt>
<button>count: {count}</button>
<input type='text' placeholder='write' value={value} onChange={(e) =/> setValue(e.target.value)}/>
</Route>
<Route path='/write/second'>
<h3>second</h3>
</Route>
</BrowserRouter>
</div>
)
}
现在我们有两层路由了,我们可以设置成不同的getUserConfirmation
,同时也将文案改了改,外层的表示第一层路由的提示,内层表示第二层。App.jsx
用默认的getUserConfirmation
即window.confirm
。
完整的代码如下
// App.jsx
const App = () {
return (
<BrowserRouter>
<div>
<ul style={{marginTop: '10px'}}>
<li>
<Link to='/'>Home</Link>
</li>
<li>
<Link to='/write'>Write</Link>
</li>
</ul>
<Switch>
<Route exact path='/'>
</Route>
<Route path='/write' strict={true} forceRefresh={true} component={WriteMail}>
</Route>
</Switch>
</div>
</BrowserRouter>
);
}
export default App;
// WriteMail.jsx
function WriteMail(props) {
const [value, setValue] = useState('');
const [count, setCount] = useState(0);
function redirectMsg(location, type = 0) {
return type + ': Go to ' + location.pathname;
}
const getUserConfirmationInWrite = (message, callback) => {
console.log('getUserConfirmationInWrite -> ', );
Modal.confirm({
title: message,
onCancel: () => {
setCount(count => count - 1);
callback(false);
},
onOk: () => {
setCount(count + 1);
callback(true);
}
});
}
return (
<div>
<h1>Write</h1>
<Prompt when={true} message={(a) => redirectMsg(a, '外层')}></Prompt>
<ul style={{marginTop: '10px'}}>
<li>
<Link to='/write/first'>First</Link>
</li>
<li>
<Link to='/write/second'>Second</Link>
</li>
</ul>
<Router getUserConfirmation={getUserConfirmationInWrite}>
<Route path='/write/first'>
<h3>first</h3>
<Prompt when={true} message={(a) => redirectMsg(a, '内层')}></Prompt>
<button>count: {count}</button>
<input type='text' placeholder='write' value={value} onChange={(e) => setValue(e.target.value)}/>
</Route>
<Route path='/write/second'>
<h3>second</h3>
</Route>
</Router>
</div>
)
}
export default WriteMail;
现在我们在WriteMail
里面的getUserConfirmationInWrite
就可以写组件内的业务逻辑(setCount
)了。
上面的代码里面我们有两个Prompt
,分别表示从/write
开头的路径和/write/first
路径跳转时会进行二次确认。
实测发现:
- 从
/write
切换至/write/first
,会有外层提示,从 并且我们可以看到外层提示 - 从
/write/first
切换至/write
,会先有外层提示,点击确认后再出现内层提示;如果外层提示时点击了取消,则不会再有内层提示了。
PS: 我们会发现在点击二次确认时浏览器的url可能已经提前变更了,及时在二次确认弹框时点击的是取消,但是好在内容是带确认后才会变更。
- 分类:
- Web前端
相关文章
Did you mean to use React.forwardRef()?搞懂react的createRef和forwardRef
最近在使用react过程中发现在使用ref时的一些场景,自己初步感觉react的ref没有vue那么强大。 现在我就简单看下怎么使用ref? createRef 我们直接看源码 / 阅读更多…
深入学习React时间切片,任务调度scheduler
背景 最近想起月初看到的 魔术师卡颂 (微信号:kasong999)的一个公开直播—— 《手写React优先级调度算法》 ,虽然我更倾向于认为直播内容是演示如何利用React官方同款调度库手写代 阅读更多…
React router用hooks读取routeName、根据routeName跳转
在迁移Vue至React的过程中遇到了一些路由相关的问题,在Vue项目中经常会使用routeName,毕竟使用path太长了,也记不住,我自己看了看React router也没有发现routeNam 阅读更多…
2021年的一点工作总结(一)迁移React技术栈
2021年全年的工作总结起来很简单,算是做苦力的一年吧。。。 2021年春节后就开始邮件项目从Vue迁移到React的工作以及富文本编辑器由wangEditor替换成CKEditor。 其实自己 阅读更多…
Vue和React hooks实现Select批量选择、选中条数、全选、反选实现对比
批量选择、全选、反选这些功能使用频率还是很高的,下面直接看看Vue和React分别怎么实现吧。 Vue 在使用Vue的时候是很容易实现的,我们以下列数据格式为例: const data 阅读更多…
转译:使用react hooks优化回调函数在组件间的传递,useState,useReducer?
我们先看一下使用 useState hooks写的todoList组件,里面我们需要层层传递回调函数。 import React, { useState } from "react& 阅读更多…