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前端
相关文章
使用next.js服务端渲染经历
上周末的时候打算把自己的网站从vue的ssr转换为react的ssr,鉴于之前在vue中是用的原生的ssr,这次想在react中试试框架,所以首选的就是next.js。 第一次用next.js,根据 阅读更多…
项目Vue转成React hooks可能存在的问题--急需类似setState回调
假设在Vue中有如下三个方法,并且初始时 this.a = ‘a’; this.b = ‘b’; funA() { this.a = '1221 阅读更多…
对React Hooks的Capture value特性的理解
之前我的项目里面很多功能都是用的事件驱动,所以下面的实例也会更多地使用监听事件的回调函数。 我们先看下测试代码 const {useEffect ,useState, useRef, us 阅读更多…
Did you mean to use React.forwardRef()?搞懂react的createRef和forwardRef
最近在使用react过程中发现在使用ref时的一些场景,自己初步感觉react的ref没有vue那么强大。 现在我就简单看下怎么使用ref? createRef 我们直接看源码 / 阅读更多…
改造富文本编辑器wangEditor成react组件
我们知道wangEditor常用的功能是editor实例的 txt.html() 和 txt.text() 方法,尤其是 txt.html() 方法,这是一个类似与jQuery常用的那种get和se 阅读更多…
React执行调度流程梳理笔记
触发更新 我们最常见的触发更新的方式就是更新state了,可以分别从类组件和函数组件看看这时会发生什么。 类组件之 setState: 当触发 setState 本质上是调用 enque 阅读更多…