9-react-路由

SPA:单页面web应用(single page web application)

  1. 整个应用只有一个完整的页面
  2. 点击页面中的链接不会刷新页面,只会做页面的局部刷新
  3. 数据通过Ajax请求获取,并在前端异步展现

路由

什么是路由

  1. 一个路由 就是一个映射关系(key:value)

  2. key为路径,value可能是function或component

路由的分类

 1.后端路由

  1. value是function,用来处理客户端提交的请求
  2. 注册路由:router.get(path,function(req,res))
  3. 工作过程:当node接到一个请求时,根据路径找到匹配的路由,调用路由中的函数来处理请求,返回响应数据

2.前端路由

  1. 浏览器端路由,value是component,用于展示页面内容
  2. 注册路由:<Router path='/test' component={Test}>
  3.  工作过程:当浏览器的path变为/test时,当前路由组件就变为Test组件

实例 

App.jsx 

<div className="list-group">

	{/* 原生html中,靠<a>跳转不同的页面 */}
	{/* <a className="list-group-item" href="./about.html">About</a>
	<a className="list-group-item active" href="./home.html">Home</a> */}

	{/* 在React中靠路由链接实现切换组件--编写路由链接 */}
	<Link className="list-group-item" to="/about">About</Link>
	<Link className="list-group-item" to="/home">Home</Link>
</div>


<div className="panel-body">
	{/* 注册路由 */}
	<Route path="/about" component={About}/>
	<Route path="/home" component={Home}/>
</div>

 因为注册路由需要使用<BrowserRouter></BrowserRouter>包裹,可以直接包裹住App组件

import {BrowserRouter} from 'react-router-dom'
ReactDOM.render(
	<BrowserRouter>
		<App/>
	</BrowserRouter>,
	document.getElementById('root')
)

NavLink和Link的区别

路由链接也可以使用NavLink

<NavLink>是<Link>的一个特定版本,会在匹配上当前的url的时候给已经渲染的元素添加参数,组件的属性有

  1. activeClassName(string):设置选中样式,默认值为active
  2. activeStyle(object):当元素被选中时,为此元素添加样式
  3. exact(bool):为true时,只有当导致和完全匹配class和style才会应用
  4. strict(bool):为true时,在确定为位置是否与当前URL匹配时,将考虑位置pathname后的斜线
  5. isActive(func)判断链接是否激活的额外逻辑的功能
<div className="list-group">

	{/* 原生html中,靠<a>跳转不同的页面 */}
	{/* <a className="list-group-item" href="./about.html">About</a>
	<a className="list-group-item active" href="./home.html">Home</a> */}

	{/* 在React中靠路由链接实现切换组件--编写路由链接 */}
	<NavLink activeClassName="cumt" className="list-group-item" to="/about">About</NavLink>
	<NavLink activeClassName="cumt" className="list-group-item" to="/home">Home</NavLink>
</div>

封装NavLink

因为NavLink中的属性太多了,所以封装为一个组件,每次调用组件名称就好了(懒是第一生产力)

export default class MyNavLink extends Component {
	render() {
		// console.log(this.props);
		return (
			<NavLink activeClassName="cumt" className="list-group-item" {...this.props}/>
		)
	}
}

之后再写路由链接写这个就好了,不过注意Home也就是标签体,其实是标签中的一个属性children,所以再MyNavLink组件中不需要传过去,只需要展开props就好了

<MyNavLink to="/home">Home</MyNavLink> 

Switch单一匹配

在注册路由那里包裹一个switch实现单一匹配,当匹配到一个时就不再向下进行匹配了

<Switch>
	<Route path="/about" component={About}/>
	<Route path="/home" component={Home}/>
	<Route path="/home" component={Test}/>
</Switch>

Redirect

一般写在所有路由的最下方,当上边的路由都不匹配时就使用这个路由

<Switch>
	<Route path="/about" component={About}/>
	<Route path="/home" component={Home}/>
    //当以上都不匹配时,就显示这个路由
	<Redirect to="/about"/>
</Switch>

二级路由

注意,二级路由需要写上父级路由的路径

<div>
	<ul className="nav nav-tabs">
		<li>
			<MyNavLink to="/home/news">News</MyNavLink>
		</li>
		<li>
			<MyNavLink to="/home/message">Message</MyNavLink>
		</li>
	</ul>
	{/* 注册路由 */}
	<Switch>
		<Route path="/home/news" component={News}/>
		<Route path="/home/message" component={Message}/>
		<Redirect to="/home/news"/>
	</Switch>
</div>

 向下一级路由传递参数的三种方式

向路由组件传递参数

    1.params参数

        路由连接:携带参数<Link to={`/demo/${name}/${age}`} ></Link>

        注册路由声明接收:<Route path='/demo/:name/:age' component={test}/>

        接收使用参数:this.props.match.params

    2.search参数

        路由链接:<Link to={`/demo/${name}/?id=id&name=name`} ></Link>

        注册路由无需注册

        接收参数:const {search}=this.props.location

                 //我们接收到的是urlencoded编码格式的字符串,需要借助querystring库转换为对象

                 const result=qs.parse(search.slice(1))  //把问号去掉

    3.state参数

        路由链接:<Link to={{pathname='/demo',state={id:id,name:name}}} ></Link>

        注册路由无需声明  

        //刷新也是可以保留住参数

        接收参数:this.props.location.state

1.param参数

路由连接:携带参数<Link to={`/demo/${name}/${age}`} ></Link>

注册路由声明接收:<Route path='/demo/:name/:age' component={test}/>

接收使用参数:this.props.match.params

  render() {
        const {messageNews}=this.state
        return (
            <div>
                <ul>
                    {
                        messageNews.map(messageObj=>{
                            return  (
                                    <li key={messageObj.id}>
                                        {/* 向组件传递params参数 */}
                                        <Link to={`/home/home-message/detail/${messageObj.id}/${messageObj.title}`}>{messageObj.title}</Link>&nbsp;&nbsp;
                                    </li>
                            )
                        })
                    }
                   
                </ul>
                    {/* 声明接收params参数 */}
                <Route path="/home/home-message/detail/:id/:title" component={Deatils}/>
            </div>
            
        )
    }
    render() {
        const {details}=this.state
        // 接收params参数
        const {id,title}=this.props.match.params
        const findResult=details.find(findObj=>{
            return findObj.id===id
        })
        return (
            <ul>
                <li>id:{id}</li>
                <li>title:{title}</li>
                <li>favorite:{findResult.content}</li>
            </ul>
        )
    }

2.search参数

路由连接:携带参数<Link to={`/demo/?name=${name}&age=${age}`} ></Link>

注册路由声明接收:<Route path='/demo' component={test}/>

接收使用参数:this.props.match.location

接收方法如下

    render() {
        const {details}=this.state
        // 接收params参数
        // const {id,title}=this.props.match.params

        //接收search参数
        const {search}=this.props.location
        // const {id,title}=qs.parse(search)  这种方法不行,对象前会有一个?
        // 一个对象想转换为urlcoded编码可以使用 qs.stringify(obj)
        //一个urlencoded编码的字符串想转换为对象为qs.parse()
        const {id,title}=qs.parse(search.slice(1))
        const findResult=details.find(findObj=>{
            return findObj.id===id
        })
        return (
            <ul>
                <li>id:{id}</li>
                <li>title:{title}</li>
                <li>favorite:{findResult.content}</li>
            </ul>
        )
    }

3.state参数

路由链接: <Link to={{pathname:'/home/home-message/detail',state:{id:messageObj.id,title:messageObj.title}}}>{messageObj.title}</Link>

注册路由:

{/* state参数 无需声明接收正常写路由即可*/}

<Route path="/home/home-message/detail" component={Deatils}/>

接收参数:const {id,title}=this.props.location.state||{}

路由跳转push与replace 

 push是放入,可以回退到之前的页面,而replace是替换,不可以回退,默认是push

replace可以实现无痕浏览,只需在路由链接中加入replace属性就好

 <Link replace to={{pathname:'/home/home-message/detail',state:{id:messageObj.id,title:messageObj.title}}}>{messageObj.title}</Link>

编程式路由导航

以replace方式访问:

replace跳转+携带params参数

this.props.history.replace(`/home/message/detail/${id}/${title}`)

 

replace跳转+携带search参数

this.props.history.replace(`/home/message/detail?id=${id}&title=${title}`)

 

replace跳转+携带state参数

this.props.history.replace(`/home/message/detail`,{id,title})

以push方式访问:

push跳转+携带params参数

this.props.history.push(`/home/message/detail/${id}/${title}`)

 

push跳转+携带search参数

this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)

 

push跳转+携带state参数

this.props.history.push(`/home/message/detail`,{id,title})

 

this.props.history.goBack()

this.props.history.goForward()

this.props.history.go(-2)

 

BrowserRouter与HashRouter的区别

1.底层原理不一样:

            BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。

            HashRouter使用的是URL的哈希值。

2.path表现形式不一样

            BrowserRouter的路径中没有#,例如:localhost:3000/demo/test

            HashRouter的路径包含#,例如:localhost:3000/#/demo/test

3.刷新后对路由state参数的影响

            (1).BrowserRouter没有任何影响,因为state保存在history对象中。

            (2).HashRouter刷新后会导致路由state参数的丢失!!!

4.备注:HashRouter可以用于解决一些路径错误相关的问题。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值