React router的Route应用

Route 是 React Router中用于配置路由信息的组件,每当有一个组件需要根据 URL 决定是否渲染时,就需要创建一个 Route。

react-router 中的很多特性都与 React 保持了一致,比如它的声明式组件、组件嵌套,当然也包括 React 的状态机特性。

1.path

每个Route都需要一个path属性,path属性是一个url,当URL匹配一个Route时,这个Route中定义的组件就会被渲染出来。

2.Route渲染组间的方式

(1)Component

component的值是一个组件,当URL和Route匹配时,Component属性定义的组件就会被渲染。

<Route path="/mycom" component={MyCom} >

(2)Render

Render 值是一个函数,这个函数返回一个React元素。这种方式方便地为待渲染的组件传递额外的属性。

<Route path=‘/mycom’  render={(props) => {

 <MyCom {…props} data={extraProps} /> //MyCom 组件接收了一个额外的data属性

}}>

</Route>

(3)children

Children的值也是一个函数,函数返回要渲染的React元素。与前面不同是,无论是否匹配成功,children返回的组件都会被渲染。匹配不成功时,match属性为null。

<Route path="/myCom" render={(props) => {

 <div className={props.match ? 'active' : ''}>

   <Foo {…props} data={extraProps} />

 </div>

}}

</Route>

如果Route匹配当前URL,待渲染元素的根节点div的class将设置成active.

3.多级路由

在路由里面继续写路由,挂载组件,就可以实现多级路由。路由嵌套实现。

<Route path=‘/myCom’ component={myCom}>
  <Route path=‘/myCom/sonCom’ component={SonCom}></Route>
</Route>

如果多级路由嵌套的层次太深,那我们写子路由的path就会特别麻烦,所以可以这样:

<Route path=‘/mycom’  render={(props) => {
  <Route path={`${props.match.path}/sonCom`} component={SonCom} />
}}>
</Route>

Match是从props解构出来,match.path就是我们当前这个路由的路径,这样不管嵌套多深,都可以写上一级的路由

4.动态传参

/foodlist/:id,传过去的值就在路由挂载组件的props中,props里有个match, match中有个params, 注意:props只在路由挂载的组件才有

<Route path=‘/foodlist/:id’ component={MyCom} />

MyCom 组件的props中就可以获取到id

可以在一个组件中用 this.props.history.push(“/path”, {name: “hellow”}), 来进行传参,传过去的值在props.location.state中

5.withRouter

一个典型的高阶组件,如果我们既想实现点击跳转,又不想用Link的a标签,我们可以用withRouter给我们吐出来一个实现点击跳转路由的组件。 Eg.

import { withRouter } from 'react-router-dom’;

//使用自定义的组件:

<CustomNavLink to="/food">food</CustomNavLink>

<CustomNavLink to="/wiki">wiki</CustomNavLink>

<CustomNavLink to="/profile">profile</CustomNavLink>

//给自定义组件实现点击功能:

const CustomNavLink = withRouter(class EnhenceCustomNavLink extends Component {

    render () {

      return (

        <li onClick={this.goto.bind(this)}>

          {

            this.props.location.pathname === this.props.to ? '>' + this.props.children : this.props.children

          }

        </li>

      )

    }

    goto () {

      this.props.history.push(this.props.to)

    }

})

假如你的组件没有路由信息,你可以使用withRouter(component)将这个组件包起来,props里面就有路由信息了。

 

这里我们顺便了解下前端路由的两种模式:Hash模式和History模式

1、Hash 模式:

 这里的 hash 就是指 url 尾巴后的 # 号以及后面的字符。Hash 也称作锚点,用来做页面的定位,可以使对应的id的元素显示在可视区域内。

Hash值的变化不会导致浏览器向服务器发出请求,而且hash改变会触发hashchange事件,浏览器的前进和后退也能对其进行控制,在html5的history出现前,基本就是使用hash来实现前段路由的。

window.location.hsah = 'qq' //设置url的hash,会在当前url后加上#qq

var hash = window.location.hsah //qq

Window.addEventListener('hashchange', function() {

 //监听hash变化,点击浏览器的前进后退会触发
)

 

2, History模式

已经有 hash 模式了,而且 hash 能兼容到IE8, history 只能兼容到 IE10,为什么还要搞个 history 呢?

首先,hash 本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了。其次,hash 的传参是基于 url 的,如果要传递复杂的数据,会有体积的限制,而 history 模式不仅可以在url里放参数,还可以将数据存放在一个特定的对象中。

window.history.pushState(state, title, url)
// state:需要保存的数据,这个数据在触发popstate事件时,可以在event.state里获取
// title:标题,基本没用,一般传 null
// url:设定新的历史记录的 url。新的 url 与当前 url 的 origin 必须是一樣的,否则会抛出错误。url可以是绝对路径,也可以是相对路径。
/*如 当前url是 https://www.baidu.com/a/,执行history.pushState(null, null, './qq/'),则变成 https://www.baidu.com/a/qq/,执行history.pushState(null, null, '/qq/'),则变成 https://www.baidu.com/qq/ */

window.history.replaceState(state, title, url)
// 与 pushState 基本相同,但这是修改当前历史记录,而 pushState 是创建新的历史记录

window.addEventListener(“popstate”, funbction(){
  // 监听浏览器前进后退事件,pushState 与 replaceState 方法不会触发     
});

window.history.back() // 后退
window.history.forward()// 前进
window.history.go(1) //前进一步,-2为后退两步,window.history.length可以查看当前历史堆栈中页面的数量

history 模式改变 url 的方式会导致浏览器向服务器发送请求,需要在服务器端做处理:如果匹配不到任何静态资源,则应该始终返回同一个 html 页面。

 

我们再顺便了解下:用户访问的URL后面加入# 号的知识

1. #号的含义:

#号代表网页中的一个位置,# 号后面的内容就是该位置的一个标记,eg.

http://www.example.com/index.html#print

访问该地址,浏览器页面会自动滚动到print 位置,print显示在可视区域

//为页面指定位置的有两种方式:
1)加锚点 <a name=“print”></a> 
 (2)<div id=“print”></div>

2.Http请求不包括#部分

比如访问上面的链接,实际发出的请求是:

GET /index.html HTTP/1.1

Host: www.example.com

#号后面的任何字符,都会被解析为位置标志符,比如:

http://www.example.com/?color=#fff

实际发出的请求是:

GET /?color= HTTP/1.1
Host: www.example.com

这并不是我们所期望的,可以对#号转义 #转为23%

http://www.example.com/?color=23%fff

 

3.改变网页的#号部分,不会触发网页的重载

http://www.example/com/index.html#location1
http://www.example.com/index.html#location2 
//改变#号后面的内容,不会重新触发服务器的请求,也就是#号后面的内容对服务器端没影响

4.改变#号后面的内容,可以修改浏览器的访问历史

每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。

5.window.location.hash 可以读到#号后面的内容

来判断网页是否发生了变化,给window.location.hash赋值时,就是增加了一条浏览器的历史访问记录

6. onhashchange 是HTML5增加的可以监听hash改变的接口:

window.onhashchange = func;
<body onhashchange="func();">
window.addEventListener("hashchange", func, false);

对于不支持onhashchange的浏览器,可以用setInterval监控location.hash的变化。

7.Google抓取#的机制

默认情况下,Google的网络蜘蛛忽视URL的#部分。

如果你希望Ajax生成的内容被浏览引擎读取,那么URL中可以使用"#!",Google会自动将其后面的内容转成查询字符串_escaped_fragment_的值。

 

 

 

posted on 2019-07-02 10:01  清水伊梦  阅读(6527)  评论(0编辑  收藏  举报