模块开发之react-router使用(八)

模块开发之react-router使用(八)

前言

路由其实决定了链接跳转到哪个界面。
比如http://localhost:8080/app/list,正常情况下链接发送到后端,由后端决定返回的页面,但由于现在前端技术的发展,模块化开发,前端可以自己决定返回的页面内容,这就是本文需要解释的路由的概念。即路由决定跳转到哪个界面。

路由是用来区分一个网站不同功能模块的地址,浏览器通过访问同一站点下的不同路由,来访问网站不同的功能。同样路由也让开发者区分返回的内容。

·React-router是一个非常好有的路由插件,它从整体上管理整个应用上的路由跳转。

本文件使用ES6模块加载方式,不是CommonJS,CMD,AMD模块规范。React-Router4由3部分组件,react-router,react-router-domreact-router-native。其中react-router是核心模块,集合react-router-domreact-router-native功能在一起,网络开发只要引入react-router-dom即可,他已经暴露了react-router核心模块里接口

引入模块

EC6引入模块方式

import { HashRouter as Router, Route, Switch, Redirect } from 'react-router-dom'

import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom'

2种方式只有HashRouter as RouterBrowserRouter as Router的不同,as声名别名。

简单例子

先上个简单的例子看一下。

import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const BasicExample = () => (
  <Router>
    <div>
      <ul>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/about">About</Link>
        </li>
      </ul>
      <hr />
      <Route exact path="/" component={Home} />
      <Route path="/about" component={About} />
    </div>
  </Router>
);

const Home = () => (
  <div>
    <h2>Home</h2>
  </div>
);

const About = () => (
  <div>
    <h2>About</h2>
  </div>
);
export default BasicExample;

简单介绍,BasicExample是对象名,也是该模块导出的模块对象, () => ();是箭头函数或Lambda表达式。原函数是function():void{},即无参的函数。
下面是关于react-router相关概念。
由于每个路由器都会维护一个History对象,其实作用是为了前进后退功能,所以所有组件都必需写在Router(具体是BrowserRouter还是HashRouter由客户定义)标签里,即BrowserRouter 必需是最外层标签,只能这里才能前进后退
而且Router下只能有一个子标签child
Link用于跳转,类似a标签的href的功能。Route在整体上拦截路由请求。

BrowserRouter和HashRouter路由器

BrowserRouterHashRouterRouter路由器的2种类型。
2种路由的特点
1. 只能有一个子child.比如

<Router>
    <div>

     </div>
</Router>
  1. 区别于下面要讲的路由标签Route

两者区别

BrowserRouter是使用 React-Router 的应用推荐的 history方案。它使用浏览器中的 History API 用于处理 URL,创建一个像localhost:8080/list/123这样真实的 URL 。这很容易出现刷新页面后报404的错误。因为真实请求会向服务器发送请求,但服务器根本没有这个页面所以会报错,这是使用BrowserRouter路由的坑点。
想解决这个问题参考这里React-Router browserHistory浏览器刷新出现页面404解决方案,其本质的原理就是利用服务端将任何请求都指向index.html,而在React应用中index.html又刚好通过React-Router配置了相应的路由,我们让服务器返回index.html,后面就交给前端路由来实现无刷新加载对应页面。

HashRouter使用 URL 中的 hash(#)部分去创建路由,举例来说,用户访问本地服务/about,实际会看到的是http://localhost/#/about

总结一下
假如有一个 Link 标签,点击后跳转到 /test/about。

BrowserRouter: http://localhost:8080/test/about
HashRouter: http://localhost:8080/#/test/about
如果有服务器端的动态支持,建议使用 BrowserRouter,否则建议使用 HashRouter。

Route

要点:
1. 可以放在页面任意位置
2. 匹配URL里的路径名(即域名之后部分),只要匹配就会被渲染,除非在条件语句里。
3. Route标签更多的用于渲染页面,跳转用Link
语法如下

<Route exact path="路径" component={React组件} />

exact:可选参数,决定是否是精确匹配,不填就是模糊匹配,
例如<Route path="/test" component={Test} />
1. 当路径名为’/’时, path不匹配
2. 当路径名为’/test''/test/1'时, path匹配

若只想匹配/test则使用exact参数,即<Route exact path="/test" component={Test} />

match值对象

当匹配成功后,匹配的结果封装到一个叫match对象里。而这个match对象可以传到component对象的react组件里。
match包含的信息有如下几点:
1. url :与当前location路径名所匹配部分
2. path :路由的地址
3. isExactpath 是否等于 pathname
4. params :从path-to-regexp获取的路径中取出的值都被包含在这个对象中。

例如:

<Route path={`test/:topicId`} component={Topic} />

如’test/:topicId‘中:topicId这种写法意味着/test/后的路径名将会被获取并存在match.params.test中。例如,路径名’/test/6’会获取到一个对象{ topicId: '6' }
而Topic组件声明,接收match对象,获得topicId值如下:

const Topic = ({ match }) => (
  <div>
    <h3>{match.params.topicId}</h3>
  </div>
);

不同的组件提供形势访问方式不同
Route component组件使用 this.props.match
Route render纯函数使用match对象 as ({ match }) => ()
Route children 一个返回React element的函数使用match对象as ({ match }) => ()

Route确认渲染哪个组件方式

当满足path条件时,决定渲染哪个React组件有3种方式,其实是指定不同的参数
1. component : 指定React组件。即component={组件名},最终使用React.createElement创建。例如<Route path="/test" component={Test} />
2. render : 一个返回React element的函数。当匹配成功后调用该函数。该过程与传入component参数类似,并且对于行级渲染与需要向元素传入额外参数的操作会更有用。使用render参数的组件则会调用render函数。
例如 :

<Route path='/page' render={(props) => (
  <Page {...props} data={extraProps}/>
)}/>

 <Route path="/one" render={() => <h3>One</h3>} />
  1. children : 一个返回React element的函数。与上述两个参数不同,无论route是否匹配当前location,其都会被渲染。用的少。

嵌套使用Route

例如

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        {/* 使用 /messages/:id 替换 messages/:id */}
        <Route path="/messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)

其中IndexRoute匹配”/“路径,即根目录。

路由匹配方式

  1. 路由器按照先后顺序匹配
  2. 如果使用绝对路径,可直接找到,如果使用相当路径,要从父路径开始拼完整路径。
  3. 路径语法
    • :paramName : 匹配一段位于 /、? 或 # 之后的 URL。 命中的部分将被作为一个参数
    • () :在它内部的内容被认为是可选的
    • * : 匹配任意字符(非贪婪的)直到命中下一个字符或者整个 URL 的末尾
      例如
<Route path="/hello/:name">         // 匹配 /hello/michael 和 /hello/ryan
<Route path="/hello(/:name)">       // 匹配 /hello, /hello/michael 和 /hello/ryan
<Route path="/files/*.*">           // 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg

当你点击Link时,URL会更新,组件会被重新渲染,但是页面不会重新加载。只要用在TAB页面或导航页上切换页面
语法

<Link to="{location}">

一个基本的location对象为{ pathname: '/', search: '', hash: '', key: 'abc123' state: {} }
当直接输入字符串路径例如/login,会转换成location对象{ pathname: '/login'}
尽量使用绝对路径,即“/路径

官方例子
React-Router4.x中文文档

猜你喜欢

转载自blog.csdn.net/achenyuan/article/details/80704641