react之路由

  • 功能:让用户从一个视图(组件)导航到另一个视图(组件)
  • 前端路由是一套映射规则,在React中,是URL路径与组件的对应关系
  • 使用React路由简单来说,就是配置路径和组件
路由的使用 1、安装路由
npm i -S react-router-dom
2、相关组件
  1. Router组件:包裹整个应用,一个React应用只需要使用一次
    Router: HashRouter和BrowserRouter
    - HashRouter: 使用URL的哈希值实现 (localhost:3000/#/first)
    - BrowserRouter:使用H5的history API实现(localhost3000/first)
  2. Link/NavLink组件:用于指定导航链接(a标签)
    • to属性:会被编译成 a标签的href属性 to='/main' || to='{{pathname='/main'}}'
    • activeClassName属性:指定样式名
    • Link 不会显示按钮的高亮显示, NavLink 来替代它
    • 最终Link会编译成a标签,
  3. Route组件:指定路由展示组件相关信息(组件渲染)
    • path属性:路由规则,这里需要跟Link组件里面to属性的值一致
    • exact属性:严格匹配, 为true是表示严格匹配,为false时为正常匹配。
    • component属性:展示的组件
    • render属性:用于页面组件级别的权限管理
      react之路由
      文章图片
3、使用
步骤一:定义路由模式
  • 主入口index.js中定义路由模式
import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import store from './store' import {HashRouter ar Router} from 'react-router-dom' ReactDom.render(, document.getElementById('root') )

步骤二:组件内渲染路由 + 路由声明式导航
  1. 导入渲染组件
  2. Route路由渲染组件
  3. 使用Link或NavLink组件完成声明式导航的定义
import React, { Component } from 'react' import { Route, Link } from 'react-router-dom'const Home = () => (Home) const About = () => (About) const DashBord = () => (DashBord)class App extends Component { render() { return ( <>
    {/* 声明导航*/ }
  • Home
  • About
  • DashBord
{/* path:可访问的url路径 component:匹配成功的渲染的组件 exact:严格匹配模式 Route组件中匹配成功,渲染会自动在this.props中添加路由导航相关属性方法 */ } ); } }export default App;

路由的扩展 1、路由参数
在Route定义渲染组件时给定动态绑定的参数
  1. params:在路由目标页面中
    • 动态路由定义:
    • 传递:
    • 获取:this.props.match.params
  2. query:通过地址栏中的 ?key=value&key=value,
    • 传递:
    • 获取:this.props.location.search
    • 备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
  3. state:隐式转参,用于数据的收集
    • 传递:
    • 获取:this.props.location.state
    • 作用:埋点---收集数据统计
2、switch组件
  1. 通常情况下, path和component是一一对应的关系.
  2. Switch可以提高路由匹配效率(单一匹配).
  3. 为了更好地匹配规则,轻易不要舍弃 。
  4. Redirect:路由从定向,一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
import { Route,Switch } from 'react-router-dom'
  • ContactUs

3、Route组件三种渲染方式
1、component
  1. 参数:对象
  • 直接使用组件类--使用最多的方式
  • 缺点:不能把父组件中的数据通过props传递给路由组件中
  1. 参数:函数} />
  • 使用函数,可以写条件判断,根据条件来渲染不同的组件
  • 可以通过props来完成父组件中的数据向路由渲染组件传递
  • 缺点:每次匹配路由成功都会从新创建组件---效率低下,不建议使用
{ return }}/>

2、render
} />
  • render方式渲染,使用函数方式
  • 如果匹配相同,则不重新创建,效率高
  • 建议如果组件对象方式渲染(函数方式)推荐使用render
    { if(this.state.count==1){ return }else{ retutn } }}/>

3、children
  1. 组件对象方式:必须匹配到path的路由规则才渲染和render与component一样
  2. 函数方式:不管是否和path匹配都渲染
    1. match为null表示当前路由规则和path不匹配,如果为对象则匹配成功
    { if(match){ return children渲染 } }} />

3种渲染区别总结
比较一
  1. component:可以使用组件类渲染或内联式方式渲染
  2. render:只能使用函数
  3. children:使用函数或直接使用组件对象
比较二
  1. component:内联式渲染方式在每次匹配路由成功后都将创建一个新组件
  2. render,children不会,所以用内联式方式建议使用后两者,内联方式渲染组件,推荐用render
比较三
  1. children的值是一个函数时,无论当前地址和path路径匹不匹配,都将会执行children对应的函数,当children的值为一个组件时,当前地址和path不匹配时,路由组件不渲染
  2. children函数方式渲染,会在形参中接受到一个对象,对象中match属性如果当前地址匹配成功返回对象,否则null
4、编程式路由导航
借助this.prosp.history对象上的API对操作路由跳转、前进、后退
  1. this.prosp.history.push()
  2. this.prosp.history.replace()
  3. this.prosp.history.goBack()
  4. this.prosp.history.goForward()
  5. this.prosp.history.go()
注:默认组件中没有this.props.history方法,需要通过withRouter高阶组件(装饰器)来进行包裹,才能得到。
this.props.history.push(path) 或 this.props.history.push({ pathname:'', search:'', state:{} })

路由监听
在App.jsx组件中可以添加路由监听
constructor(props) { super(props); this.props.history.listen(route=>console.log(route)) }

5、withRouter高阶组件
作用:把不是通过路由切换过来的组件中,将react-router 的 history、location、match 三个对象传入props对象上
  • 如果在你想在一般组件使用 路由组件所特有的API 时, 就要借助 withRouter
  • withRouter可以加工一般组件, 让一般组件具备路由组件所特有的API
  • withRouter的返回值是一个新组件
  1. 引入withRouter
    import { withRouter} from 'react-router-dom'
  2. 执行一下withRouter export default withRouter(Cmp)`
import React, { Component } from 'react' import {withRouter} from 'react-router-dom' class Header extends Component { // 回退 back = () => { this.props.history.goBack() }// 前进 forward = () => { this.props.history.goForward() }/// go go = () => { this.props.history.go(2) }render() { // console.log('一般组件',this.props) return (React Router Demo ) } }export default withRouter(Header)

6、自定义路由
  • 定义一个普通组件可以是类组件也可以是函数式组件
  • 父组件能向子组件传值 props
  • 不管路由规则是否匹配都要显示组件 Route children渲染方式(函数式)
  • 注意点:react中组件是大写字母开头 html也是组件
import React from 'react' import {withRouter,Route} from 'react-router-dom' const MyLink = props=>{ const gourl=()=>{ props.history.push(props.to) } const Tag=props.tag||'a' const Active=props['active-class']||'router-active-class' return ( { if(match){ return {props.children} } return {props.children} }}> ) } export default withRouter(MyLink)

7、多级路由
在有一些功能中,往往请求地址的前缀是相同的,不同的只是后面一部份,此时就可以使用多级路由(路由嵌套)来实现此路由的定义实现。
例: 路由规则如下
admin/index
admin/user
当前组建的请求uri地址(父组件路由uri) let pathname=this.props.match.path return( 用户首页 用户列表 写在admin组件内,admin组件通过route来进行渲染 )

8、重定向与404
  • 重定向 from从哪里来 to重定向到何处去

  • 404设置

默认:匹配规则是从上项下的,一只匹配下去
switch组件:解决一直匹配问题,只要有一个符合;路由规则就停止匹配
重定向from来源,to跳转的页面

React Router 基本原理 【react之路由】React Router依赖于history.js,它是一个独立的第三方js库。可以用来兼容在不同浏览器、不同环境下对历史记录的管理,拥有统一的API。
  • 老浏览器的history: 通过hash来存储在不同状态下的history信息,对应createHashHistory,通过检测location.hash的值的变化,使用location.replace方法来实现url跳转。通过注册监听window对象上的hashChange事件来监听路由的变化,实现历史记录的回退。
  • 高版本浏览器: 利用HTML5里面的history,对应createBrowserHistory, 使用包括pushStatereplaceState方法来进行跳转。通过注册监听window对象上的popstate事件来监听路由的变化,实现历史记录的回退。
  • node环境下: 在内存中进行历史记录的存储,对应createMemoryHistory。直接在内存里pushpop状态。

    推荐阅读