您的位置:首页 > Web前端 > React

react-router 4.x(路由)

2017-08-08 18:13 381 查看
一、react-router

1.安装

npm install react-router-dom --save


2.使用,我们直接上菜,想必大家已经饿了。

//index.js
import "../css/reset.css";
import "../css/common.css";
import React,{ Component } from "react";
import { render } from "react-dom";
import {
BrowserRouter as Router,
Route,
Link
}from 'react-router-dom';
import App from "../Components/app";
import Shop from "../Components/shop.js";
import Owner from "../Components/owner.js";

class Hello extends Component{
render(){
return (
<Router>
<div>
<ul>
<li><Link to="/">App</Link></li>
<li><Link to="/shop">Shop</Link></li>
<li><Link to="/owner">Owner</Link></li>
</ul>
<hr />
<Route exact path="/" component={App} />
<Route path="/shop" component={Shop} />
<Route path="/owner" component={Owner} />
</div>
</Router>
)
}
}
render(
<Hello />,
document.getElementById('root')
)


和之前的版本一样,Router还是一个容器,但他的角色却改变了,4.0的react-router可以任意的放标签了,这意味着使用方式的改变,但真正的路由通过Route定义。Link标签依然可以看作a标签。点击会改变浏览器Url的hash值,通过Route标签来捕获这个url并返回component属性中定义的组件。Route标签内有个exact关键字,它是用来将”/”做唯一的匹配。如果没有这个的话,在匹配其他的同时也会匹配到当前。一试便知。

通过Router路由的组件可以拿到一个match参数,这个参数是一个对象。其中包含几个数据:

isExact: 刚才已经说过这个关键字,表示是为做全等匹配。

params: path中包含的一些额外数据。

path: Route组件path属性的值。

url: 实际url的hash值。

3.Router标签

hashHistory 老版本浏览器的history
browserHistory h5的history
memoryHistory node环境下的history,存储在memory中。


4.Route标签

在例子中你可能注意到了Route的几个prop

exact
path
component
render


他们都不是必填项,如果path没有赋值,那么此Route就是默认渲染的。

Route的作用就是当url和Route中path属性的值匹配时,就渲染component中的组件或者render中的内容。

说到这,那么Route内部是怎样实现这个机制的呢,不难猜测肯定是用一个匹配的方法来实现的,那么Router是怎么知道url更新了然后重新进行匹配并且渲染呢?

整理一下思路,在一个web应用中,改变一个url无非两种方式。一种是利用超链接进行跳转,另一种是使用浏览器的前进后退功能,前者在触发Link的跳转事件之后再触发。后者是Route利用的history的listen方法来监听url的变化。为了防止引入新的库,Route创作者选择使用html5中的popState事件。只要点击了浏览器的前景或者后退按钮,这个事件就会触发,我们来看一下Route的代码。

class Route extends Component {
static propTypes: {
path: PropTypes.string,
exact: PropTypes.bool,
component: PropTypes.func,
render: PropTypes.func,
}

componentWillMount() {
addEventListener("popstate", this.handlePop)
}

componentWillUnmount() {
removeEventListener("popstate", this.handlePop)
}

handlePop = () => {
this.forceUpdate()
}

render() {
const {
path,
exact,
component,
render,
} = this.props

//location是一个全局变量
const match = matchPath(location.pathname, { path, exact })

return (
//有趣的是从这里我们可以看出各属性渲染的优先级,component第一
component ? (
match ? React.createElement(component, props) : null
) : render ? ( // render prop is next, only called if there's a match
match ? render(props) : null
) : children ? ( // children come last, always called
typeof children === 'function' ? (
children(props)
) : !Array.isArray(children) || children.length ? ( // Preact defaults to empty children array
React.Children.only(children)
) : (
null
)
) : (
null
)
)
}
}


Route在组件将要Mount的时候,添加popState事件的监听,每当popState事件触发,就使用forceUpdate强制刷新,从而基于当前的location.pathname进行一次匹配。再根据结果渲染。

componentWillMount() {
addEventListener("popstate", this.handlePop)
}
handlePop = () => {
this.forceUpdate()
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  react