控制与切换

路由控制与切换

编码控制

使用 router 对象

在基础示例中我们讨论过,传入 Route 配置中的组件会被进行包裹传入gopush等可用于手动路由控制的 Props,而对于非路由配置中的组件,React Router 同样提供了便捷的withRouter,允许以高阶函数的方式将router对象属性传入组件中。withRouter会在每次路由跳转时重新渲染被包裹的组件。这里我们编写一个简单的示例,即在组件树的某个组件中显示当前的位置信息。

// 简单的用于显示当前路径信息的组件
class ShowTheLocation extends React.Component {
  static propTypes = {
    location: PropTypes.object.isRequired
  };

  render() {
    return <div>You are now at {this.props.location.pathname}</div>;
  }
}

// 类似于 Redux 中的 connected,将组件链接到 router,并且将 router 的属性以 Props 传入到组件中
const ShowTheLocationWithRouter = withRouter(ShowTheLocation);

每个<Router />都会将一个 router 对象绑定到 React Context 中,并且方便<Router />与子级别的<Route>, <Link>, <Prompt> 进行通信。虽然这个接口比较方便,不过鉴于其主要是用于内部通信,并且 Context 本身也是实验性的接口,有可能会在 React 未来版本中发生变化,因此我们建议尽量谨慎使用该接口。context.router 对象的属性为:

context.router = {
  ...history,
  match
};

自定义 history 对象

当我们使用 BrowserRouterHashRouterMemoryRouter 以及 NativeRouter 作为根路由时,它们会自动地创建 history 对象,该对象能够被自动注入到 React 组件中;不过很多时候我们也需要在组件外,譬如状态管理代码中进行些路由控制。此时如果我们需要在组件树之外使用 history 对象,就需要手动创建 history 对象,然后在声明根 Router 对象时引用该对象:

// history.js
import { createBrowserHistory } from 'history'
export default createBrowserHistory()


// index.js
import { Router } from 'react-router-dom';
import history from './history'


ReactDOM.render((
  <Router history={history}>
  <App />
  </Router>
), document.getElementById('root'))


// nav.js
import history from './history'


export default function nav(loc) {
  history.push(loc);
}

我们在上文中介绍过 historybrowser historyhash historymemory history的区别,而history对象还包含以下属性与方法:

  • length - (number) 历史记录的数目
  • action - (string) 当前动作 (PUSH, REPLACE, 或者 POP)
  • location - (object) 当前地址路径,可能包含以下属性
    • pathname - (string) URL 的路径
    • search - (string) URL 中查询字符串
    • hash - (string)URL hash fragment
    • state - (string) push(path, state) 函数传入的state参数,仅可用于 browser history 或者 memory history
  • push(path, [state]) - (function) 向当前 history stack 压入新记录
  • replace(path, [state]) - (function) 替换当前 history stack 顶部记录
  • go(n) - (function) 将 history stack 指针移动n
  • goBack() - (function) 等价于 go(-1)
  • goForward() - (function) 等价于 go(1)
  • block(prompt) - (function) 避免跳转

参数传递

转场控制

权限控制

/**
 * Returns the pages available when the authentication is complete
 * @private
 * @returns {XML}
 * @constructor
 */
function PrivateRoutes() {
  return (
    <div>
      {/* this div here is worthless */}
      <Route exact path="/about" component={About} />
      <Route exact path="/" component={Home} />
       
    </div>
  );
}

/**
 * Returns all the pages that are public and do not require any authentication
 * @private
 * @returns {XML}
 * @constructor
 */
function PublicRoutes() {
  return (
    <div>
      {/* this div here is worthless */}
      <Route exact path="/login" component={Login} />
      <Route exact path="/contact" component={Contact} />
       
    </div>
  );
}

/**
 * All the application routes
 * @returns {XML}
 */
function Routes({ isAuthenticated }) {
  return (
    <Provider store={store}>
      <Router>
        <div>
          {/* this div here is worthless */}
          <PublicRoutes />
           {" "}
          {do {
            if (isAuthenticated) {
              <PrivateRoutes />;
            } else {
              <Route
                path="/"
                render={() => <Redirect to={{ pathname: "/login" }} />}
              />;
            }
          }}
           
        </div>
      </Router>
    </Provider>
  );
}
class App extends Component {
  //snip our user stuff from earlier

  render() {
    return (
      <BrowserRouter>
        <Match exactly pattern="/" component={HomePage} />
        <Match pattern="/login" component={Login} />
        <MatchWhenAuthorized pattern="/protected" component={ProtectedPage} />
         
      </BrowserRouter>
    );
  }
}

const MatchWhenAuthorized = ({ component: Component, ...rest }) => (
  <Match
    {...rest}
    render={renderProps =>
      isAuthenticated() ? (
        <Component {...renderProps} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: renderProps.location }
          }}
        />
      )
    }
  />
);

转场提示

上一页
下一页