react router页面跳转二次确认弹窗及样式、业务逻辑自定义

boyanx3个月前技术教程10

我们在编辑页面时如果需要跳走通常会需要给用户提示,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我嫩就会有二次确认弹窗了,也就是从/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,  '外层')}/>
        </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);
  }}
/>

所以我们需要修改下App.jsx了,我们这里引入antd的Modal做弹窗

// App.jsx
const App = () {
    const getUserConfirmation = (message, callback) => {
        Modal.confirm({
          title: message,
          onCancel: () => {
            callback(false);
          },
          onOk: () => {
            callback(true);
          }
        });
    }
    return (
      </browserrouter><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,  '外层')}/>

      <ul style={{marginTop: '10px'}}>
        <li>
          <link to='/write/first'/>First
        </li>
        <li>
          <link to='/write/second'/>Second
        </li>
      </ul>

      <router getUserConfirmation={getUserConfirmationInWrite}>
        <route path='/write/first'>
          <h3>first</h3>
          <prompt when={true} message={(a) => redirectMsg(a, '内层')}/>
          <button>count: {count}</button>
          <input type='text' placeholder='write' value={value} onChange={(e) =/> setValue(e.target.value)}/>
        </prompt></route>
        <route path='/write/second'>
          <h3>second</h3>
        </route>
      </router>
    </prompt></div>
  )
}

现在我们有两层路由了,我们可以设置成不同的getUserConfirmation App.jsx用默认的。 完整的代码如下

// App.jsx
const App = () {
    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;
// WriteMail.jsx
function WriteMail(props) {
  const [value, setValue] = useState('');
  const [count, setCount] = useState(0);

  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,  '外层')}/>

      <ul style={{marginTop: '10px'}}>
        <li>
          <Link to='/write/first'>First</Link>
        </li>
        <li>
          <Link to='/write/second'>Second</Link>
        </li>
      </ul>
      <dialog ref={dialogRef}>dialog的内容</dialog>

      <Router getUserConfirmation={getUserConfirmationInWrite}>
        <Route path='/write/first'>
          <h3>first</h3>
          <Prompt when={true} message={(a) => redirectMsg(a, '内层')}/>
          <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路径跳转时会进行二次确认。 实测发现:

  1. /write切换至/write/first,会有外层提示,从 并且我们可以看到外层提示
  2. /write/first切换至/write,会先有外层提示,点击确认后再出现内层提示;如果外层提示时点击了取消,则不会再有内层提示了。

PS: 我们会发现在点击二次确认时浏览器的url可能已经提前变更了,及时在二次确认弹窗时点击的是取消,但是好在内容是带确认后才会变更。

标签: js弹窗

相关文章

极致舒适的Vue弹窗使用方案_vue页面弹窗太多如何处理

一个Hook让你体验极致舒适的Dialog使用方式!Dialog地狱为啥是地狱?因为凡是有Dialog出现的页面,其代码绝对优雅不起来!因为一旦你在也个组件中引入Dialog,就最少需要额外维护一个v...

苹果iOS9 Safari加入贴心功能:烦人弹窗请滚粗

苹果在最新的iOS9beta测试版中为手机版的Safari浏览器加入了一项十分实用的新功能,让用户们可以不用再忍受一些网站上的恶意行为。日前有不少用户在浏览网页时遭遇了“呼叫中心骗局”,即在查看网页期...

js逆向,web逆向技巧分享_js逆向工程

当我们抓取网页端数据时,经常被加密参数、加密数据所困扰,如何快速定位这些加解密函数,尤为重要。在这里分享一些技巧,如有遗漏,欢迎补充。所需工具:浏览器(Chrome,Edge等)搜索全局搜索适用于根据...

javascript超长知识归纳总结_javascript常用

基本概念javascript简称js,是一种脚本语言,用来操作HTML中的节点,产生动态效果。包括三大模块。ECMAScript:是javascript核心语法;json是其中一种轻量级的数据交换格式...

JavaScript 关闭浏览器 (不弹出提示框)

一段JavaScript脚本程序, 负责关闭窗口, 如果网页不是通过脚本程序打开的(window.open()), 调用window.close()脚本关闭窗口前, 必须先将window.opener...

给大伙支两招,一键去网页跳转弹窗

很多网页都加入了一个鸡贼的操作——「打开 App 阅读全文」。明明可以一次性把内容展示出来,非得给你隐藏一半,剩下一半需要下载 App 才能看。要不是隔着一条网线,这种话说到一半的人,真的,应该拖出去...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。