使用npm来进行安装
npm install --save react-router react-router-dom
ReactRouter动态传值
-
设置, 以:开始的,然后紧跟着你传递的key(键名称)名称。
<Route path="/list/:id" component={List} />
-
Link上传递值
<li><Link to="/list/123">列表</Link> </li>
to属性的值可以是一个字符串,也可以是一个location(pathname, hash, state和search)对象。
-
组件上接收并显示传递值
componentDidMount(){ console.log(this.props.match) }
然后在浏览器的控制台中可以看到打印出的对象,对象包括三个部分:
-
patch:自己定义的路由规则,可以清楚的看到是可以产地id参数的。
-
url: 真实的访问路径,这上面可以清楚的看到传递过来的参数是什么。
-
params:传递过来的参数,key和value值。
-
理解和使用Route
Route组件可以使用如下的属性:
-
path属性,字符串类型,它的值就是用来匹配url的。
-
component属性,它的值是一个组件。在path匹配成功之后会绘制这个组件。
-
exact属性,这个属性用来指明这个路由是不是排他的匹配。
-
strict属性, 这个属性指明路径只匹配以斜线结尾的路径。
还有其他的一些属性,可以用来代替component属性。
-
render属性,一个返回React组件的方法。传说中的rencer-prop就是从这里来的。
-
children属性,返回一个React组件的方法。只不过这个总是会绘制,即使没有匹配的路径的时候
数的时候是用component属性就可以满足。但是,某些情况下你不得不使用render或children属性。
ReactRouter重定向-Redirect使用
-
标签式重定向
这个一般用在不是很复杂的业务逻辑中,比如我们进入Index组件,然后Index组件,直接重定向到Home组件。
//引入Redirect import { Link , Redirect } from "react-router-dom"; //引入Redirect后,直接在render函数里使用就可以了 <Redirect to="/home/" />
-
编程式重定向
//直接在构造函数constructor中加入下面的重定向代码 this.props.history.push("/home/");
进阶
React router的Route中component和render属性的使用
-
component ---只有当位置匹配时才会渲染的 React 组件
当您使用 component(而不是 render 或 children )Route 使用从给定组件 React.createElement 创建新的 React element。这意味着,如果您为 component 道具提供了内联功能,则每次渲染都会创建一个新组件。这会导致现有组件卸载和安装新组件,而不是仅更新现有组件。当使用内联函数进行内联渲染时,使用 render 或者 children(如下所示)
-
render: func ---这允许方便的内联渲染和包裹,而不是上面那种不想要的重新安装的解释
您可以传递一个在位置匹配时调用的函数,而不是使用属性为您创建新的 React element component,该 render 属性接收所有相同的 route props 的 component 渲染属性。
警告: Route component 优先于 Route render 因此不要在同一个 Route 使用两者。
通过一个小例子来说明:
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route} from "react-router-dom";
class Bar extends React.Component {
componentDidMount() {
console.log("componentDidMount")
}
render() {
return (
<div>Bar</div>
)
}
}
class App extends React.Component {
constructor(prop) {
super(prop);
this.state = {idx: 1}
}
handleClick = () => {
this.setState(state => ({idx: state.idx + 1}))
};
render() {
return (
<div>
<div>
{this.state.idx}
<button onClick={this.handleClick}>add</button>
</div>
<div>
<BrowserRouter>
<Route component={Bar}/>
</BrowserRouter>
</div>
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
//上面的代码中,App组件内有一个简单的Bar组件,通过component属性被Route引用。
//<Route component={Bar}/>
//此时在页面中点击按钮,Bar组件的componentDidMount并不会被触发。
假设现在需要在Bar组件中接受App中的idx,需要将idx作为props传递给Bar,此时可以写成如下代码
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route} from "react-router-dom";
class Bar extends React.Component {
componentDidMount() {
console.log("componentDidMount")
}
render() {
const {idx} = this.props;
return (
<div>in Bar : {idx}</div>
)
}
}
class App extends React.Component {
constructor(prop) {
super(prop);
this.state = {idx: 1}
}
handleClick = () => {
this.setState(state => ({idx: state.idx + 1}))
};
render() {
return (
<div>
<div>
{this.state.idx}
<button onClick={this.handleClick}>add</button>
</div>
<div>
<BrowserRouter>
<Route component={() => (<Bar idx={this.state.idx}/>)}/>
</BrowserRouter>
</div>
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
然而此时点击按钮,发现Bar的componentDidMount一直被调用,所以正确的写法应该是:
<Route render={() => (<Bar idx={this.state.idx}/>)}/>
//此时Bar组件就不会出现重复的unmounting和mounting了。
其背后的原理在于,react在比较组件状态以便决定如何更新dom节点时,首先要比较组件的type和key。在使用<Route component={() => (<Bar idx={this.state.idx}/>)}/>时,由于调用了React.createElement,组件的type不是Bar这个类,而是一个匿名函数。App组件每次render时都生成一个新的匿名函数,导致生成的组件的type总是不相同,所以会产生重复的unmounting和mounting。
react路由懒加载(异步组件)------react-loadable
-
安装
cnpm install react-loadable
-
封装loadable
首先,我们建一个util src/util/loadable.js
import React from 'react'; import Loadable from 'react-loadable'; //通用的过场组件 const loadingComponent =()=>{ return ( <div>loading</div> ) } //过场组件默认采用通用的,若传入了loading,则采用传入的过场组件 export default (loader,loading = loadingComponent)=>{ return Loadable({ loader, loading }); }
-
调用
import loadable from '../util/loadable' const Home = loadable(()=>import('@pages/home'))
react-loadable是以组件级别来分割代码的,这意味着,我们不仅可以根据路由按需加载,还可以根据组件按需加载。
网友评论