上节课我们介绍了嵌套路由,有了嵌套路由我们就可以来完成一些更加复杂的页面了,这节课呢我们来介绍一点新的东西。不知道大家还记不记得我们之前说一般组件和路由组件的最大的区别就是,组件接收到的props
不同,一般组件是我传什么,就收到什么,而路由组件是路由组件会固定传入三个属性进去。这节课我们就来说一说这个方面的东西。
回顾
当然在,开始这节课的内容之前,我们先来对上节课的内容来做一个简单的回顾。
- 不要轻易开启严格匹配,否则可能会无法匹配子级路由
- 嵌套路由就是多级路由,刻在某一路由下再包含其他路由
- 嵌套路由的路径要加上父路由的路径
- 路由匹配是按照注册顺序逐层注册匹配的
以上便是上节课的主要要点,接下来我们开始我们这节课的内容。
需求效果
我们首先先来回忆一下上节课中,我们案例一直是在拿News
来举例。可能大家没注意到我们的Message
的列表里面都是一个个的链接。我们现在要的效果是什么呢?就是当我们点击其中的链接,我们要在页面下方展示这个链接中的详情。
就和图中展示的内容类似,我们点击message001
然后就在页面下方展示这条message
的详情内容。而且浏览器地址路径也要变成/home/message/1
。
分析
就刚才的效果,大家有没有觉得我们又多出来一个导航区和展示区?只不过这次导航区不再是导航栏,而是一个链接列表了。那么从层级上来是,这一块是不是就应该是一个三级路由了?还有一点,我们这个展示区的结构其实都是一样的,只不过我们点击的时候展示了不同的内容,那么我们是不是就不用抽成三个组件来写了?这样我们可以省掉很多代码,不然如果这里如果有 10 条messsage
或者说更多的话我们就得写很多小组件,这种就造成了很严重的代码冗余。
那么我们将这个展示区值作为一个公用的组件就会很方便,里面要展示的结构是固定的,那么内容直接通过props
传进去就好了啊。但是问题来了。这个组件是不是也要根据路由来管理?因为我们都是根据浏览器地址的不同路径来控制不同内容的展示的,所以说这也还是一个路由组件。那么路由组件我们怎么给他传参数?
一般组件我们可以通过手动在组件标签中来写标签属性传入props
,可是路由组件呢?路由组件我们没有写组件标签啊,我们也没法手动传props
啊,路由组件收到的是路由自动传进去的三个固定属性啊。那么我们应该怎么处理呢?先别着急,我们先把能实现的给实现掉。
导航区
我们也别把这一块写死了,我们用state
来生成这段导航区
export default class Message extends Component { state = { messageArr:[ { id:1, title:"message001" }, { id:2, title:"message002" }, { id:3, title:"message003" }, ] } render() { const { messageArr } = this.state return ( <ul> {messageArr.map(msg=><li key={msg.id}><a href="/#">{msg.title}</a></li>)} </ul> ) } }
来看代码,我们初始化了state
,state
中有id
和title
,那么遍历一下生成相应的a
标签,但是往哪咱还没想好先放着。这样我们来看一下效果:
展示区
现在我们的导航区已经完成了,那么展示区我们说了是一个固定结构,我们单独抽成一个组件,就叫Details
吧,我们来先把组件的结构给实现出来。
export default class Details extends Component { render() { return ( <ul> <li>ID: ???</li> <li>TITLE: ???</li> <li>CONTENT: ???</li> </ul> ) } }
因为我们还不知道要展示什么,所以先用问号来代替,那么我们在什么事才会展示Details
组件?是不是在我们点击了Message
中的导航区才会展示?那么我们就要在Message
中来引入Details
,然后来看一下展示效果:
设置路由
展示是不是正常?但是我们这么展示对吗?当然不对啊,我们都没有点怎么可以展示呢?所以说我们是不是就要把每条消息的<a>
改成路由链接?那么我来问大家,这里我们需要用NavLink
吗?是不是不需要?我们没有要高亮的需求。所以直接用Link
就行了
export default class Message extends Component { state = { messageArr: [ { id: 1, title: "message001" }, { id: 2, title: "message002" }, { id: 3, title: "message003" }, ] } render() { const { messageArr } = this.state return ( <div> <ul> {messageArr.map( msg => <li key={msg.id}> <Link to="/home/message/detials">{msg.title}</Link> </li> )} </ul> <Route path="/home/message/detials" component={Details} /> </div> ) } }
我们先来看一下代码,我们把<a>
改成了<Link>
,既然我们设置了路由链接,那么我们是不是就要注册路由?因为是三级路由所以我们路由链接或者是注册路由时候,路径我们都得把/home/message
都给加上。然后现在我们来看一下效果:
没有点击的时候就没有任何展示了。,当我们点击一下:
点击之后,我们就可以看到我们的Details
组件就正常展示出来了。但是我们的需求并不是这样,我们要展示的是每条消息都要有内容。那么我们就要把每条消息的信息传给Detatils
组件。而且路径是消息的id
。那么我们应该如何处理呢?
携带params
参数
我们上面说的那么热闹,但是参数传不进去都是白瞎,那么我们接下来来讲一下如何给路由组件传参,我们先来讲最简单那的一种,就是params
参数。
提到params
参数大家应该有过一点了解,我们在学习ajax
的时候,是不是学过ajax
请求可以携带 3 种参数?第一种是query
参数,第二种是params
参数,第三种是body
参数。路由组件参数其中的一种其实就是params
参数,这个params
参数就可以直接写在路径中。
那么我看一下,我们通过参数要把什么传到Details
组件中?是不是一个是id
另一个是title
?可能有人要说,还有一个content
啊。我们先别急,我们先把这两个先传过去,只要能传过去还用再在乎content
吗?那么怎么传呢?
export default class Message extends Component { state = {...} render() { const { messageArr } = this.state return ( <div> <ul> {messageArr.map( msg => <li key={msg.id}> <Link to={`/home/message/detials/{msg.id}/{msg.title}`}> {msg.title} </Link> </li> )} </ul> <Route path="/home/message/detials/:id/:title" component={Details} /> </div> ) } }
我们来看一下代码,这是什么意思?其他的是不是都不用管,我们先单看我们的Link
标签,这个to
属性这么写是什么意思?我是不是要把msg.id
和msg.title
传给Details
组件?这其实就是传递params
参数的方法。但是我如果光在<Link>
中写的话是不行的,因为注册路由的时候只是会认为你这是模糊匹配,所以说我们再来看注册路由这里,我们要用:id
和:title
来接收我们传入的参数。只有这样Details
组件才能收到数据。
那么问一下,现在我们数据也传了,注册路由的时候也接收了,那么接收到的参数存到哪去了?是不是Details
组件的props
中去了?我们来打印一下看看:
我们先看上面地址路径是不是正常details
后面是id
在后面就是title
,然后来看控制台,在match
属性中是不是有一个params
属性?这里面就是我们传入进去的参数。那么我们在Details
组件中来使用这些参数吧:
const data = [ { id: 1, content: "Hello world!" }, { id: 2, content: "Hello React!" }, { id: 3, content: "Hello jingxun!" }, ] export default class Details extends Component { render() { const { id, title } = this.props.match.params const findResult = data.find(d=>d.id.toString() === id); return ( <ul> <li>ID: {id}</li> <li>TITLE: {title}</li> <li>CONTENT: {findResult.content}</li> </ul> ) } }
我们现在Details
组件中定义一个变量来作为我们mock
出来的数据,然后解构赋值,从props
中取出id
和title
,然后再通过id
从data
中拿到content
,然后展示到页面上。我们来看一下效果:
这样我们便成功得将我们想要的效果展示在了页面上。
总结
params
参数可以直接写咋路由链接路径中- 注册路由时要声明接收参数
param
参数存放在props
中的match.params
中。
Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.
Link of this article:https://work.lynchow.com/article/pass_params_to_route_component/