javascript - React router 仅模式路由

标签 javascript url-routing reactjs react-router

我的应用程序中确实有一个公共(public)区域和一个私有(private)区域,我希望能够在公共(public) View 中的任何地方显示登录模式对话框。模态应该有自己的路线。第二个用例是私有(private)区域中的配置文件模式。

问题是当模态显示时,背景中的当前 View 会消失,因为模态不是当前 View 路由的子节点。

由于我不想将相同的模式添加到每个可能的 View 路线,所以这里有一个问题:是否可以将模式路线与其父路线分离并在应用程序中的任何地方显示它们而无需主要内容呈现?最好的方法是什么?我找到了 this issue但似乎不是同一个问题。

模式路由上的浏览器刷新不会在后台呈现任何内容,但这是我可以忍受的问题。

最佳答案

我认为您最好的选择可能是使用隐藏的 state ,或查询字符串(用于永久链接),或两者兼而有之,尤其是当模式(例如登录模式)可以显示在任何页面上时。万一你不知道,React Router 暴露了 state历史 API 的一部分,允许您将数据存储在 URL 中实际上不可见的用户历史记录中。

这是我想到的一组路线;你可以跳straight into the working example on JSBin如果你想。您还可以查看生成的示例应用程序 in its own window因此您可以看到 URL 的变化(它使用哈希定位策略来与 JSBin 兼容)并确保刷新按您的预期工作。

const router = (
  <Router>
    <Route component={LoginRedirect}>
      <Route component={LocationDisplay}>
        <Route path="/" component={ModalCheck}>
          <Route path="/login" component={makeComponent("login")} />
          <Route path="/one" component={makeComponent("one")} />
          <Route path="/two" component={makeComponent("two")} />
          <Route path="/users" component={makeComponent("users")}>
            <Route path=":userId" component={UserProfileComponent} />
          </Route>
        </Route>
      </Route>
    </Route>
  </Router>
);

让我们研究一下这些路线及其组成部分。

首先,makeComponent只是一个方法,它接受一个字符串并创建一个 React 组件,该组件将该字符串呈现为标题,然后呈现它的所有子项;这只是创建组件的一种快速方法。

LoginRedirect 是一个有一个目的的组件:检查路径是否为/login或者如果有 ?login当前路径上的查询字符串。如果其中任何一个为真,当前状态不包含 login键,它设置 login状态键为true .如果匹配任何子路由(即始终呈现组件),则使用该路由。
class LoginRedirect extends React.Component {
  componentWillMount() {
    this.handleLoginRedirect(this.props);
  }

  componentWillReceiveProps(nextProps) {
    this.handleLoginRedirect(nextProps);
  }

  handleLoginRedirect(props) {
    const { location } = props;
    const state = location.state || {};
    const onLoginRoute = location.query.login || location.pathname === "/login";
    const needsStateChange = onLoginRoute && !state.login;
    if (needsStateChange) {
      // we hit a URL with ?login in it
      // replace state with the same URL but login modal state
      props.history.setState({login: true});
    }
  }

  render() {
    return React.Children.only(this.props.children);
  }
}

如果您不想使用查询字符串来显示登录模式,您当然可以修改此组件以满足您的需要。

接下来是LocationDisplay ,但它只是我为 JSBin 演示构建的一个组件,它显示有关当前路径、状态和查询的信息,并且还显示了一组演示应用程序功能的链接。

登录状态对于下一个组件很重要, ModalCheck .该组件负责检查 login 的当前状态。 (或 profile ,或可能的任何其他)键并根据需要显示关联的模态。 (JSBin demo实现了一个 super 简单的modal,你的肯定会更好。:)它还在主页上以文本形式显示了modal检查的状态。)
class ModalCheck extends React.Component {
  render() {
    const location = this.props.location;
    const state = location.state || {};
    const showingLoginModal = state.login === true;
    const showingProfileMoal = state.profile === true;

    const loginModal = showingLoginModal && <Modal location={location} stateKey="login"><LoginModal /></Modal>;
    const profileModal = showingProfileMoal && <Modal location={location} stateKey="profile"><ProfileModal /></Modal>;

    return (
      <div style={containerStyle}>
        <strong>Modal state:</strong>
        <ul>
          <li>Login modal: {showingLoginModal ? "Yes" : "No"}</li>
          <li>Profile modal: {showingProfileMoal ? "Yes" : "No"}</li>
        </ul>
        {loginModal}
        {profileModal}
        {this.props.children}
      </div>
    )
  }
}

其他一切都是相当标准的 React Router 东西。唯一需要注意的是 Link里面 LocationDisplay这显示了如何链接到应用程序中的各个位置,在某些情况下显示模式。

首先,您当然可以使用 login 链接(和永久链接)到任何要求它显示登录模式的页面。键入查询字符串:
<Link to="/one" query={{login: 1}}>/one?login</Link>
<Link to="/two" query={{login: 1}}>/two?login</Link>

当然,您也可以直接链接到 /login网址。

接下来,请注意您可以显式设置状态以便显示模式,这不会更改 URL。但是,它将保留在历史记录中,因此可以按照您的预期使用后退/前进,并且刷新将在同一背景页面的顶部显示模式。
<Link to="/one" state={{login: true}}>/one with login state</Link>
<Link to="/two" state={{login: true}}>/two with login state</Link>

您还可以链接到当前页面,添加特定的模式。
const path = props.location.pathname;

<Link to={path} state={{login: true}}>current path + login state</Link>
<Link to={path} state={{profile: true}}>current path + profile state</Link>

当然,取决于您希望应用程序如何工作,并非所有这些都适用或有用。例如,除非模态是真正全局的(也就是说,它可以显示 无论路线如何 ),这可能工作正常,但对于显示给定用户的个人资料这样的模态,我可能会使其成为单独的路线,将其嵌套在父级中,例如:
<Route path="/users/:id" component={UserPage}>
  <Route path="/users/:id/profile" component={UserProfile} />
</Route>
UserProfile ,在这种情况下,将是呈现模式的组件。

您可能想要进行更改的另一个示例是在历史记录中存储某些模式;如果您不想,请使用 replaceState而不是 setState作为适当的。

关于javascript - React router 仅模式路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28795085/

相关文章:

javascript - 如何使用 Jest 测试导入/导出?

javascript - 使用 Jquery 在悬停时换回图像

seo - 国际化和搜索引擎优化

javascript - 路由在 angularjs 中不起作用

javascript - 如何使用 es6 过滤对象值

javascript - 转移 { ..this.props } 但排除某些

javascript - 如何测量脚本执行和*解析*时间?

javascript - 无法理解 JavaScript 函数返回

外部脚本中的 JavaScript 函数

jquery - JQuery Post 调用中的相对 URL