本文共 7638 字,大约阅读时间需要 25 分钟。
路由是根据不同的 url 地址展示不同的内容或页面。 一个针对React而设计的路由解决方案、可以友好的帮你解决React components 到 URl之间的同步映射关系。
https://reacttraining.com/react-router/web/guides/quick-start
使用React路由之前,我们需要先安装 react-router-dom
这个包。比如:
npm install --save react-router-dom
import React from 'react'import { HashRouter, Route, Redirect, Switch, NavLink } from 'react-router-dom'
HashRouter :表示一个路由的跟容器,将来,所有的路由相关的东西,都要包裹在 HashRouter 里面,而且,一个网站中,只需要使用一次 HashRouter 就好了;
Route :表示一个路由规则, 在 Route 上,有两个比较重要的属性, path
component
path
表示要匹配的路由,component
表示要展示的组件Redirect:内置两个属性 from
: 匹配到的路径 to
:要跳转的路径
{ props.children} { /* 动态路由 */}
完整代码如下:
//配置路由-路由组件import React from 'react'import { HashRouter,Route,Redirect,Switch} from 'react-router-dom'import Center from '../views/Center'import Cinema from '../views/Cinema'import Detail from '../views/Detail'import Film from '../views/Film'export default function MRouter(props) { return ({ props.children} )}/*function Route(props){ console.log(props.path) if(location.hash===props.path){ return{ /* 模糊匹配 */} { /* 动态路由 */} } return null}*/
注意:
a. <Redirect from="/" to="/film"/>
b. exact 精确匹配 (Redirect 即使使用了exact, 外面还要嵌套Switch 来用)
c. Warning: Hash history cannot PUSH the same path; a new entry will not be added to the history stack,这个警告只有在hash 模式会出现。在NavLink 加上 replace 来解决.
模糊匹配与精准匹配
默认情况下,路由中的匹配规则,是模糊匹配的。上面这种匹配方式,全都匹配到了cinema组件,不会匹配到search组件。
如果想让路由规则,进行精确匹配,可以为Route添加 exact
属性。
import React from 'react'import { Route, Switch,Redirect } from 'react-router-dom'import Comingsoon from './films/Comingsoon'import Nowplaying from './films/Nowplaying'export default function Film() { return ()}大轮播
Link :表示一个路由的链接(a链接),就好比 vue 中的 <router-link to=""></router-link>
NavLink (有高亮)
to
:要跳转的路径(相当于a标签中的"herf"属性)activeClassName
:用来做选中样式的切换(相当于vue的 active-class
)import React from 'react'import { NavLink} from 'react-router-dom'import './Tabbar.css'export default function Tabbar() { return ()}/* function NavLink(props){ return {props.childrenm} }*/
电影 影院 我的
this.$router.push()
props.history.push()
const handleChange = (id)=>{ props.history.push(`/detail/${ id}`)}
用来路由跳转的过程中传递参数,例如点击列表页某条数据,跳转到详细页。
定义动态路由:
跳转到指定动态路由:
const handleChange = (id)=>{ props.history.push(`/detail/${ id}`)}
如果我想在 Detail组件中显示路由的参数,可以通过 props.match.params
获取路由中的参数。
vue: this.$route.params.id
react: props.match.params.id
useEffect(() => { console.log("获取详情id,发ajax给后端",props.match.params.id) }, [props.match.params.id]){ this.props.match.params.id}
完整代码如下:
import { useEffect,useState} from 'react'import axios from 'axios'export default function Nowplaying(props) { const [list, setlist] = useState([]) useEffect(() => { axios.get("/test.json").then(res=>{ setlist(res.data.data.films) }) }, []) const handleChange = (id)=>{ //编程式导航 props.history.push(`/detail/${ id}`) } return ({ list.map(item=>)}handleChange(item.filmId)}> { item.name} ) }
(1)this.props.history.push({ pathname : '/user' ,query : { day: 'Friday'} }) this.props.location.query.day (2) this.props.history.push({ pathname:'/user',state:{ day : 'Friday' } }) this.props.location.state.day
const check = ()=>{ return localStorage.getItem("token")}{ /* 路由拦截 */}{ /* check 有token跳到center 没有token 重定向login */}check()? : }/>
function CinemaHeader (props) { return ()}export default function Cinema () { return ()}
props 打印{},因为 CinemaHeader的父组件(Cinema) 没有给他传属性,只有Route组件才有props属性。
解决方案有:
export default function Cinema (props) { return ()} function CinemaHeader (props) { return ({ console.log("leftclick"); props.history.push('/cinema/search') }}> )}
// 父组件把Route传过来的props展开传给子组件,子组件就可以用props.historyexport default function Cinema (props) { return ()} function CinemaHeader (props) { return ( )}
import {withRouter} from 'react-router-dom' // 导入 withRouter function CinemaHeader(props) { return ()}export default withRouter(CinemaHeader) // withRouter 包裹子组件
原理:利用高阶组件封装出来的一个组件
/* withRouter 高阶函数 高阶组件 (High-order-component) == HOC (输入低阶组件, 得到高阶组件)*/ function withRouter(MyComponent){ ..... ..... return function(){ return} }/* function add(a,b){ return a+b}function AAA(add){ return function(a,b){ return add(a*a,b*b) }}// var result = add(1,2)// console.log(result)var advancedAdd = AAA(add)console.log(advancedAdd(1,2)) */
自己封装高阶组件(复用思想)
import React,{ useEffect} from 'react'function withCenter(MyComponent){ return function(){ useEffect(() => { window.onresize = ()=>{ console.log("resize") } }, []) return}} function Center(props) { console.log(props) return ( center)}export default withCenter(Center)
history模式
BrowserRouter 没有#,后端找不到会报404
// 配置路由的文件import React from 'react'import { BrowserRouter, Route, Switch } from 'react-router-dom'import Film from '../views/Film'import Login from '../views/Login'export default function MyRouter (props) { return ()}
css样式 会全局影响,react没有scope ,需要把css 文件改为 filename.module.css
//导入import style from './Film.module.css'// 用的时候通过style.样式名film-header
转载地址:http://pqyrf.baihongyu.com/