美文网首页
react路由

react路由

作者: 指尖轻敲 | 来源:发表于2018-08-01 15:59 被阅读53次

react-router-dom


最近开始学习reactr-router,但是看了好多文章都有问题,后来才发现是react-router 4做了很大的改动,遵循 Just Component 的 API 设计理念。reactr-router被拆分为reactr-routerreactr-router-domreactr-router-native三部分。reactr-router提供核心的API,其余两个则提供两个特定的运行环境(浏览器和react-native)所需的组件。因此所有的路由组件导入都改为了从react-router-dom导入。

安装

注意如果是用create-react-app脚手架的话,注意安装方式(yarn或者npm),详情参考另外一篇react脚手架搭建

npm install --save react-router-dom;
npm install --save react-router-redux;
npm install --save react-router-config;

使用

先看一下基本写法:

一级路由,做正常的路由切换
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom'
class App extends Component {
  render() {
    return (
      <Router basename='/route'>
        <div>
          <Route path="/" exact component={Home}></Route>
          <Route path="/mime" component={Mime}></Route>
          <Route path="/list" component={List}></Route>
          <ul>
            <li>
                <Link to="/">home</Link>
            </li>
            <li>
                <Link to="/mime">mime</Link>
            </li>
            <li>
                <Link to="/list">list</Link>
            </li>
          </ul>
        </div>
      </Router>
    );
  }
}
二级路由

在一级路由的基础上再做路由,通过props中的match属性可以获取当前的url(),然后再去拼接二级路由的path。

export default class List extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h1>列表页</h1>
        <ul>
          <li>
            <Link to={`${this.props.match.url}/details`}>详情</Link>
          </li>
          <li>
            <Link to={`${this.props.match.url}/edit`}>编辑</Link>
          </li>
        </ul>
        <Route path={`${this.props.match.url}/details`} component={Details} />
        <Route path={`${this.props.match.url}/edit`} component={Edit} />
      </div>
    );
  }
}
带参数

如果路由后面要携带参数,可以这样写(最后括号中的值表示只能是这两个值,如果没有此限制则可以是任何值)

<Route
    path={`${this.props.match.url}/:id(20|100)`}
    component={Details}
/>

在子组件中通过this.props.match.params.xx获取对应的参数

<h1>{this.props.match.params.id}</h1>
<BrowserRouter>和<HashRouter>

他们就是路由的根基,包裹在最外层。之前使用路由的肯定知道(不管是哪个版本,甚至vue的路由),路由的实现有两种方法,HashRouter是利用URL的hash部分实现,在url中会经常有个#号,主要是针对旧版浏览器。我们一般都使用BrowserRouter,它是利用H5的history API实现。

还有一种实现是针对非DOM环境的(react-native),利用内存实现。

  • basename:如果你的文件在服务器的二级目录下,就会用到它。他会在每一个路由路径前面自动添加一级目录。如下图,当我们点击list时,url中会自动添加route目录。
basename.png

该组件下只能有一个子组件,所有组件都要包裹在一层里。

<Route>

Route就是控制不同路径去对应显示内容的组件。配合Link使用。

  • exact:控制严格匹配。如果没有这个属性,当访问list时,home组件和list组件会同时被渲染。

  • path:访问的路径,如果没有该属性,那么将会匹配一切路径。

  • component:path路径对应要显示的组件。使用最多。如果要获取match等对象。可以使用this.props.match...

  • render:与component一样,可以直接在后面写要渲染的内容。可以获取到mach对象。

<Route path="/home" render={({match}) => <div>Home</div>}/>
  • children:和render是一样的功能,不过它不论是否匹配到都会调用。
<Route path="/mime" component={Mime}></Route>
<Route path="/list" children={({match})=> (
    <div>
        <h3>哈哈</h3>
        <List></List>
    </div>
)}></Route>

以上代码,不管当前匹配的是mime还是list或是其他,都会渲染list。

<Link>和<NavLink>

Link的api相对较少,上面我们使用的是最简单的to,直接跳转到一个地址。就不多说了。

  • to:还可以携带参数到指定页面,后面跟一个对象就可以。如下(可以实现页面间传参)
<Link to={{
  pathname: '/list',
  search: '?sort=name',
  state: { id: 2 }
}} />

state可以传递任何类型的参数,而且类似于post方式,可以不以明文传输。在跳转的页面中实用this.props.location.state获取数据。

  • replace:基本不用,为true时会替换掉上次访问的地址,也就是使用浏览器的回退按钮无法返回上一个页面。

NavLink很明显就是为页面导航准备的,因为导航是要有激活状态的。

  • activeClassName:激活时要渲染的样式名
<NavLink to="/mime" activeClassName='actvived'>mime</NavLink>
  • activeStyle:直接把激活的样式写在后面
<NavLink to="/mime" activeStyle={{color: red,fontSize: 20px}}>mime</NavLink>
  • exact:如果为true,只有当访问地址严格匹配时才会使用激活样式。

  • strict:如果为true,只有挡访问地址后的斜杠严格匹配(有或没有)才会使用激活样式。

  • isActive:跟一个函数,当导航激活时要做的事情。

<StaticRouter>

api中介绍说这是一个从来不会改变位置的Router。当用户没有实际点击时,因此位置也从未发生变化。这在服务端渲染很有用,因为在后台上, 我们只会渲染一次,而且不会直接地对用户的交互操作做出反应。

看下API中的案例:

import { createServer } from 'http'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { StaticRouter } from 'react-router'

createServer((req, res) => {
  // 这个context包含渲染的结果
  const context = {}
  const html = ReactDOMServer.renderToString(
    <StaticRouter location={req.url} context={context}>
      <App/>
    </StaticRouter>
  )

  // 如果使用<Redirect>,context.url将包含要重定向到的URL
  if (context.url) {
    res.writeHead(302, {
      Location: context.url
    })
    res.end()
  } else {
    res.write(html)
    res.end()
  }
}).listen(3000)
  • basename:所有位置的基本url,正确的格式应该是前面有/后面没有/
<StaticRouter basename="/main">
  <Link to="/list"/> <!--渲染出来应该是<a href="/main/list">-->
</StaticRouter>
  • location:如果是个字符串就应该是服务器上收到的url(req.url)。如果是个对象应该是一个类似{pathname, search, hash, state}的位置对象。
<StaticRouter location={{ pathname: '/home' }}>
  <App/>
</StaticRouter>
  • context:一个普通js对象,在渲染过程中组件可以向对象里添属性以存储有关渲染的信息。

我们使用它来找出渲染结果,context上下文对象是自己的,我们可以改变它。

//app上有个404组件,把status改成404
const NotFound = () => (
  <Route
    render={({ staticContext }) => {
      if (staticContext) {
        staticContext.status = 404;
      }
      return (
        <div>
          <h1>你输入的地址不正确哟!</h1>
        </div>
      );
    }}
  />
);

// 在服务端我们就可以通过判断,对这个404界面发送404响应
const context = {};
const content = renderToString(
    <Provider store={store}>
        <StaticRouter location={req.url} context={context}>
            <App />
        </StaticRouter>
    </Provider>
);
if (context.status === 404) {
    res.status(404);
}

或者判断重定向,如果有context.url就说明应用被重定向,这允许我们从服务器发送适当的重定向。

if (context.url) {
  // can use the `context.status` that
  // we added in RedirectWithStatus
  redirect(context.status, context.url)
}
<Switch>

用来包裹Route或者Redirect组件,而且不能放其他元素,用来渲染第一个匹配到的路由,不会向下继续匹配。如果不用Switch包裹的话,访问/about时下面三个组件都会被渲染。

<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
<Redirect>

将匹配到的路径重定向到一个新的地址。新的地址应该覆盖掉访问的地址。

<Route path="/game" component={Game}></Route>
<Redirect from="/home" to="game" push={true}></Redirect>
  • from:匹配到的访问的地址

  • to:重定向到的地址

  • push:为true时,重定向到的地址会添加到历史访问记录,并且无法回到之前访问的地址。

<withRouter>

withRouter可以用来包装任何自定义组件,并将historylocationmatch三个对象传入。这样组件就可以拿到路由信息。

import {withRouter} from 'react-router-dom';
const Home = withRouter(({history,location,match})=>{
  return <h1>{location.pathname}</h1>
})
history

表示浏览器历史记录的对象,可以对它进行一系列操作,有以下属性和方法:

  • length:获取历史堆栈中的条目数

  • action:获取当前操作(push/pop/replace)

  • location:获取当前位置,包括(pathname、search、hash、state、)

  • push(''):添加一个新的条目到历史堆栈(一般会用来跳转到一个新页面)

  • replace(''):替换掉当前堆栈上的条目

  • go(n):通过n个条目移动历史堆栈中的指针,向前或向后n个

  • goBack():后退一个历史条目,相当于go(-1)。

  • goForward():前进一个历史条目,相当于go(1)

  • block:防止导航

match

<Route path>如何与url匹配的信息,包含以下内容:

  • params:URL动态段解析对应的键值对

  • isExact:如果匹配整个URL则为true

  • path:<Route>匹配的路径

  • url:当前真正访问的路径

location

程序当前所在的位置。。。

react-router-redux


如果使用的react-router-redux(把react-router url的变化、参数等信息作为状态,交给redux的store管理),则可以直接从state中获取路由信息。

import {routeMiddleware} from 'react-router-redux';
const store = createStore(combineReducers, applyMiddleware(routeMiddleware));
const mapStateToProps = (router) => ({
    pathname: rourter.location.pathname
})
export default connect(mapStateToProps)(MyControl)

具体请看API

react-router-config


react-router-config是帮助我们配置静态路由的。算是比较好理解的,API只有两个方法:

matchRoutes(routes, pathname)

该方法接收两个参数(routes配置,请求路径),返回一个数组。

import { matchRoutes } from 'react-router-config'
const branch = matchRoutes(routes, '/child/23')

这个返回的数组的每一个元素包含两个属性routes和match。结构如下:

[
  {
    route: {
      path: '/app',
      component: [(Function: component)],
      routes: [Array]
    },
    match: { path: '/app', url: '/app', isExact: false, params: {} }
  },
  {
    route: { path: '/app/resources', component: [Object] },
    match: {
      path: '/app/resources',
      url: '/app/resources',
      isExact: true,
      params: {}
    }
  }
];

这个方法在服务端貌似用的多一些,自己没有用过不说太多。。。

renderRoutes(routes, extraProps = {})

该方法接受两个参数:配置的路由和要传的值。
写这篇文章的时候,react-router-config的renderRoutes方法并没有更新的npm上,其实已经实现了,不知道为什么没有上npm。看下源码:

import React from 'react';
import Switch from 'react-router/Switch';
import Route from 'react-router/Route';

const renderRoutes = (routes, extraProps = {}, switchProps = {}) =>
  (routes ? (
    <Switch {...switchProps}>
      {routes.map((route, i) => (
        <Route
          exact={route.exact}
          key={route.key || i}
          path={route.path}
          render={props =>
            (route.render ? (
              route.render(props)
            ) : (
              <route.component {...props} {...extraProps} route={route} />
            ))
          }
          strict={route.strict}
        />
      ))}
    </Switch>
  ) : null);

实际上就是在一个<Switch>中创建了多个<Route>

看一下API中给出的代码示例,路由可以进行统一的配置了,不过有个缺陷就是:在组件的render方法中还需要调用renderRoutes方法。

import { renderRoutes } from 'react-router-config'
// 配置路由
const routes = [
  { component: Root,
    routes: [
      { path: '/',
        exact: true,
        component: Home
      },
      { path: '/child/:id',
        component: Child,
        routes: [
          { path: '/child/:id/grand-child',
            component: GrandChild
          }
        ]
      }
    ]
  }
]
// 设置路由
ReactDOM.render((
  <BrowserRouter>
    {renderRoutes(routes)}
  </BrowserRouter>
), document.getElementById('root'))
// 在组件中调用方法
const Root = ({ route }) => (
  <div>
    <h1>Root</h1>
    {renderRoutes(route.routes)}
  </div>
)
const Home = ({ route }) => (
  <div>
    <h2>Home</h2>
  </div>
)
const Child = ({ route }) => (
  <div>
    <h2>Child</h2>
    {renderRoutes(route.routes, { someProp: 'these extra props are optional' })}
  </div>
)
const GrandChild = ({ someProp }) => (
  <div>
    <h3>Grand Child</h3>
    <div>{someProp}</div>
  </div>
)

相关文章

  • react从0到1的探索记录04

    18、React中的路由 React中路由的基本使用 在react中使用路由首先需要安装react的路由模块 np...

  • react学习资料八

    路由 使用react的路由就要引入react路由插件react-router.js ReactRouter 保存一...

  • React-Router知识点

    路由的分类 页面路由 hash 路由 h5路由 react路由 react-router-dom 路由方式 h5路...

  • React路由

    React 路由 一、在React中使用react-router-dom路由 安装npm install reac...

  • 有标题的文章

    React Redux 路由设计 - - React

  • React路由

    React路由 一、路由的形式 hash路由 : HashRouter history路由 : BrowserRo...

  • react-router Q & A

    什么是React 路由? React 路由是一个构建在 React 之上的强大的路由库,它可以让你向应用中快速地添...

  • 2018-12-21路由

    1.路由 React路由依赖于React Router,React Router保持UI和与URL的同步。它拥有简...

  • react-router-dom 的基本使用

    本文介绍 react 中路由的使用。在 react 中使用 路由的库为 react-router。或者是 reac...

  • react-router

    React Router 是完整的 React 路由解决方案 import React from 'react' ...

网友评论

      本文标题:react路由

      本文链接:https://www.haomeiwen.com/subject/orsymftx.html