注:大量截图动图。
一 基础路由
1. 路由链接:Nav和NavLink是Nav
NavLink是Nav的一个特定版本,NavLink可以有高亮的效果,可以设置选中的className.
<div className="box">
<div className="left-nav">
<div className="linkbtn">
<Link to="/home">home</Link>
</div>
<div className="linkbtn">
<Link to="/about">about</Link>
</div>
</div>
</div>
<div className="box">
<div className="left-nav">
<div className="linkbtn">
<NavLink to="/home">home</NavLink>
</div>
<div className="linkbtn">
<NavLink to="/about">about</NavLink>
</div>
</div>
</div>
可以看出 Nav和NavLink都可以改变路由,不同的是Navlink当前锚点有对应的class(默认为active),如果有高亮的展示应该选择NavLink。可以设置选中的className
<NavLink to="/home" className="linkbtn" activeClassName="activeLink"> home </NavLink>
2. 路由注册
<div class="right-content">
<Route path="/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
</div>
其中path的值和NavLink to属性的值一致,渲染对应的组件。
通常我们为了提高效率,减少路由继续匹配,会在外面套一个Switch标签,路由一旦匹配成功就不会继续向下匹配。
<div className="box">
<div className="left-nav">
<NavLink to="/home/person" className="linkbtn" activeClassName="activeLink">
home
</NavLink>
<NavLink to="/about" className="linkbtn">
about
</NavLink>
</div>
<div class="right-content">
<Route path="/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
<Route path="/home/person" component={Person}></Route>
</div>
</div>
此时点击‘/home/person’,路由匹配的规则是先匹配'/home',再继续匹配‘/home/person’,默认是模糊匹配,所以两个都是符合条件的,都会被渲染。
<div class="right-content">
<Switch>
<Route path="/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
<Route path="/home/person" component={Person}></Route>
</Switch>
</div>
此时路由一旦匹配到就不会继续往下,所以只渲染第一个匹配到的组件Home。
如果想要精准匹配路由则设置exact属性
<Switch>
<Route path="/home" exact="true" component={Home}></Route>
<Route path="/about" exact="true" component={About}></Route>
<Route path="/home/person" exact="true" component={Person}></Route>
</Switch>
此时匹配到的就会是'/home/person',第三个路由,渲染Person组件
二 嵌套路由
此时在home组件再嵌套一层路由:
//app.js
<div className="box">
<div className="left-nav">
<NavLink to="/home" className="linkbtn" activeClassName="activeLink">
home
</NavLink>
<NavLink to="/about" className="linkbtn">
about
</NavLink>
</div>
<div className="right-content">
<Switch>
<Route path="/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
</Switch>
</div>
</div>
//Home
<div>
<div>
<NavLink to="/home/person" className="navlink"></NavLink>
<NavLink to="/home/message" className="navlink"></NavLink>
</div>
<div>
<Switch>
<Route path="/home/person" component={Person} ></Route>
<Route path="/home/message" component={Message} ></Route>
</Switch>
</div>
</div>
特别的,嵌套的路由要加上上一级的路由,比如这里Person组件的路由不能是‘/person’,而是要加上上一级的‘/home’,写成‘/home/person’,且第一级的路由‘/home’不能是精准匹配,否则就到不了第二级。
三 传参
//message.js
state={
arr:[
{id:1,name:'xxx1',message:'yyyyyy1'},
{id:2,name:'xxx2',message:'yyyyyy2'},
{id:3,name:'xxx3',message:'yyyyyy3'},
]
}
render() {
const {arr} = this.state
return (
<div>
我是Message组件
{
arr.map(obj=>{
return <div key={obj.id} ><Link to="/home/message/list">{obj.name}</Link></div>
})
}
<hr />
<Route path="/home/message/list" component={List}></Route>
</div>
);
}
此时我点击message组件里面的路由链接,展示的都是List组件,不同的是这里我想展示我点击对应的数据,此时就要用到传参,传参有几种常见的方法:
(1)params传参
//message
路由链接传参‘/value’,路由后面对应‘/:key’,在对应的组件的props.match.params可以获取到对应的参数
<div>
我是Message组件
{
arr.map(obj=>{
return <div key={obj.id} ><Link to={`/home/message/list/${obj.id}/${obj.name}`}>{obj.name}</Link></div>
})
}
<hr />
<Route path="/home/message/list/:id/:name" component={List}></Route>
</div>
(2)search传参
在路由链接以‘key=value’这种形式传递,注册路由无需处理
接收组件可以在props.location.search取得该值
(备注:获取到的search是urlencoded编码字符串,需要借助querystring解析)
(3)state传参
该传递方式在地址栏看不到传递的参数,如果不想被看到传递的值,可以选用该方式 路由链接
组件接收通过props.location.state获取传递的参数
四 push和replace
路由默认是push方式,每一步都会在history里添加一条数据,但是在传参的时候应该使用replace,可以感受一下差别:
push
replace
这里只需要在路由链接增加repalce属性就能实现
五 总结
(1)路由链接用Link和NavLink,后者可以补充选中的class,有需要这种效果用NavLink,例如上面例子中的home/about,person/message.不用的用Link,例如message组件里的三个不同的链接。
格式为
<NavLink to="/home"activeClassName="xxx">home </NavLink>
<Link to="/home">home </Link>
注册路由用Router
<Route path="/home" component={Home}></Route>
默认为模糊匹配,要精准匹配补充exact属性
多个路由时,外层包Switch标签,提高路由匹配效率
<Switch>
<Route path="/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
<Redirect to="/home"></Redirect>
</Switch>
其中 Redirect是当路由没有匹配到时,会重定向到指定页面
(2)嵌套路由实质是一样的,要使用嵌套路由使用模糊匹配。
(3)传参分为三种方法:
- 传递params参数
// 路由链接
<Link to={`/home/message/list/${obj.id}/${obj.name}`} replace>{obj.name}</Link>
//路由注册
<Route path="/home/message/list/:id/:name" component={List}></Route>
//路由接收
const {id,name} = this.props.match.params
- 传递search参数
// 路由链接
<Link to={`/home/message/list/?id=${obj.id}&name=${obj.name}`} replace>{obj.name}</Link>
//路由注册 无需处理
<Route path="/home/message/list" component={List}></Route>
//路由接收
import qs from 'querystring'
const {id,name} =qs.parse(this.props.location.search.slice(1))
- 传递state参数(地址栏看不到传值)
// 路由链接
<Link to={{ pathname:`/home/message/list`,state:{id:obj.id,name:obj.name}}} replace>{obj.name}</Link>
//路由注册 无需处理
<Route path="/home/message/list" component={List}></Route>
//路由接收
const {id,name} =this.props.location.state||{};
(4)push和replace模式 在路由注册时,默认为push模式,每次点击路由链接都会往history增加一条数据。 replace则是直接取代最后一条数据改为当前点击路由,history数量不变 在路由链接里设置replace属性可以得到