React 路由的使用

安装并引入使用

npm i react-router-dom

HashRouter

基于hash模式:页面跳转原理是使用了location.hash、location.replace;和vue router的hash模式实现一致
比较丑:在域名后,先拼接/#,再拼接路径;也就是利用锚点,实现路由的跳转;如:http://www.abc.com/#/xx

BrowserRouter

①基于history模式:页面跳转原理是使用了HTML5为浏览器全局的history对象新增了两个API,包括 history.pushState、history.replaceState;和vue router的history模式实现一致
②更加优雅: 直接拼接路径;如:http://www.abc.com/xx
③后端需做请求处理: 切换路由后,请求接口路径会发生变化,后端需要配合,做处理

BrowserRouter在本地build打包之后访问index.html打开出现白屏的情况, 使用HashRouter则不会出现这种情况,所以本地静态页面的话选择HashRouter好一些

  //引入react核心库
  import React from 'react'
  //引入ReactDOM
  import ReactDOM from 'react-dom'
  //
  import {BrowserRouter} from 'react-router-dom'
  //引入App
  import App from './App'
  
  ReactDOM.render(
  	<BrowserRouter>
  		<App/>
  	</BrowserRouter>,
  	document.getElementById('root')
  )

注册路由

<Switch>
  <Route path="/about" component={About}/>
   <Route path="/home" component={Home}/> //加了switch 匹配到了第一个/home之后就不会继续往下匹配了 如果不加switch则所有匹配结果都会被渲染 因此加上switch可以提高匹配效率
   <Route path="/home" component={Test}/>
    <Redirect to="/404"/> //路由匹配失败 重定向到404页面
</Switch>
<NavLink to="/about">About</NavLink>
<NavLink to="/home">Home</NavLink>
<NavLink to="/home/a/b/c">Home</NavLink> //多级路由/嵌套路由即可以在home页面里注册a页面 -> a页面注册b -> b页面注册c

使用路由进行页面间的传参

​ ① params传参

刷新页面参数不消失,参数会在地址栏显示

{/* 声明接收params参数 传一个id和一个title参数 */}
<Route path="/home/message/detail/:id/:title" component={Detail}/>
{/*使用Link传递参数*/}
<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>

{/* 编程式传参 */}
this.props.history.replace(`/home/message/detail/${id}/${title}`)
this.props.history.push(`/home/message/detail/${id}/${title}`)
//Detail组件里接收params参数
 const {id,title} = this.props.match.params 

Search传参

刷新页面参数不消失,参数会在地址栏显示

{/* search参数无需声明接收,正常注册路由即可 */}
<Route path="/home/message/detail" component={Detail}/>
{/* 向路由组件传递search参数 */}
<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
{/* 编程式传参 */}
this.props.history.replace(`/home/message/detail?id=${id}&title=${title}`)
this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)

//Detail组件里接收Search的参数
//要依赖个解析参数的库
import qs from 'querystring'
const {id,title} = qs.parse(search.slice(1))

query传参

刷新页面参数消失,参数不会在地址栏显示

{/* query参数无需声明接收,正常注册路由即可 */}
<Route path="/home/message/detail" component={Detail}/>
{/* 向路由组件传递query参数 */}
<Link to={{pathname:'/home/message/detail',query: {id: msgObj.id,title: msgObj.title}>{msgObj.title}</Link>
{/* 编程式传参 */}
this.props.history.replace({pathname:'/home/message/detail',query: {id: msgObj.id,title: msgObj.title})
this.props.history.push({pathname:'/home/message/detail',query: {id: msgObj.id,title: msgObj.title})

//Detail组件里接收query的参数
const {id,title} = this.props.location.query

④ 通过state携带参数

1、BrowserRouter(history)模式下,刷新页面参数不消失,参数不会在地址栏显示,因为state保存在history对象中
2、HashRouter(hash)模式下,刷新页面参数消失!!!参数不会在地址栏显示

{/* state参数无需声明接收,正常注册路由即可 */}
<Route path="/home/message/detail" component={Detail}/>
{/* 向路由组件传递state参数 */}
<Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link>
{/* 编程式传参 */}
this.props.history.replace(`/home/message/detail`,{id,title})
this.props.history.push(`/home/message/detail`,{id,title})
//Detail组件里接收state参数
const {id,title} = this.props.location.state || {}

replace 是把当前页面干掉去往一个新页面 push是当前页面还存在,压入一个新的页面进栈

**在不同的场景,可以使用不同的传参方式(适合的才是最好的): **

  • state传参: BrowserRouter(history)模式下,刷新页面不消失;而HashRouter(hash)模式下,刷新页面会消失,但都不会暴露在url
  • params传参(动态路由): 可读性高,便于维护,当另一个页面一定需要某数据时,推荐使用
  • query传参: 虽然不会暴露在url中,但刷新页面会消失
  • search传参: 会暴露在url中,刷新页面不会消失,但取数据时需处理

withRouter可以加工一般组件,让一般组件具备路由组件所特有的API

withRouter的返回值是一个新组件

//组件里定义几个按钮 按钮点击调用以下方法就可以操作路由了 
this.props.history.goForward()//前进一步
this.props.history.goBack() //后退一步 
this.props.history.go(-2) //后退2步 数值为正则前进 为负则后退
// 以上都基于浏览器的history进行的操作 如果history页面数量小于等于一个页面则无效

//注意⚠️ 组件最后还得声明一下 withRouter
export default withRouter(XXX) //xxx为组件名

参考资料

posted @ 2022-10-15 16:07  CoderWGB  阅读(87)  评论(0)    收藏  举报