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_的值。