万物皆组件,带你一文详解react-router渲染的三种方式

803 阅读2分钟

react-router简介

react-router包含3个库

  • react-router:提供最基本的路由功能,实际使⽤的时候我们不会直接安装react-router,⽽是根据应⽤运⾏的环境选择安装react-router-dom(在浏览器中使⽤)或react-router-native(在rn中使⽤)
  • react-router-dom:都依赖react-router,所以在安装时,react-router也会⾃动安装,创建web应⽤
  • react-router-native:同上

安装

npm install --save react-router-dom

基本使用

react-router中奉⾏⼀切皆组件的思想,路由器-Router、链接-Link、路由-Route、独占-Switch、重定向-Redirect都以组件形式存在。

创建RouterPage.js

import React, { Component } from "react";
import { BrowserRouter, Link, Route } from "react-router-dom";
import HomePage from "./HomePage";
import UserPage from "./UserPage";
export default class RouterPage extends Component {
	render() {
		return (
			<div> 
				<h1>RouterPage</h1> 
				<BrowserRouter> 
					<nav> 
					<Link to="/">⾸⻚</Link> <Link to="/user">⽤户中⼼</Link>
					</nav>
 				{/* 根路由要添加exact,实现精确匹配 */} 
 				<Route exact path="/" component= {HomePage}/>
				<Route path="/user" component= {UserPage} />
			</BrowserRouter>
		</div>
 );
 }}

Route渲染内容的三种⽅式

Route渲染优先级:children>component>render。

三者能接收到同样的[route props],包括match, location and history,但是当不匹配的时候,children的match为null。

这三种⽅式互斥,你只能⽤⼀种,它们的不同之处可以参考下⽂

children:func

使用场景:有时候,不管location是否匹配,你都需要渲染⼀些内容,这时候你可以⽤children。除了不管location是否匹配都会被渲染之外,其它⼯作⽅法与render完全⼀样。

import React, { Component } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Link, Route } from "react-router-dom";
function ListItemLink({ to, name, ...rest }) {
return (
	<Route path={to} 
		children={({ match }) => (
		<li className={match ? "active" : ""}>
		 <Link to={to} {...rest}>{name} </Link>
		</li>
 		)}
	/>
 );
}
export default class RouteChildren extends Component {
	render() {
		return (
			<div> 
				<h3>RouteChildren</h3>
				<Router> 
				<ul>
					<ListItemLink to="/somewhere" name="链接1" />
					<ListItemLink to="/somewhere-else"name="链接2" />
				</ul>
				</Router>
			</div>
 );
 }}

render:func

但是当你⽤render的时候,你调⽤的只是个函数。但是它和component⼀样,能访问到所有的[route props]

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route } from "react-router-dom";
// ⽅便的内联渲染
ReactDOM.render( 
		<Router> 
			<Route path="/home" render={() => <div>Home</div>} />
		</Router>,
		node
);
// wrapping/composing
//把route参数传递给你的组件
function FadingRoute({ component: Component,...rest }) {
return (
		<Route 
			{...rest} 
			render={routeProps => (
				<Component {...routeProps} />
 			)}
		/>
 );
}
ReactDOM.render( <Router> <FadingRoute path="/cool" component= {Something} />
</Router>,
node
);

component: component

场景:只在当location匹配的时候渲染。

import React, {Component, useEffect} from "react";
import {BrowserRouter as Router, Route} from "react-router-dom";
export default class RouteComponePage extends
	Component {
		constructor(props) {
			super(props);
			this.state = {
				count: 0
 			};
 		}
	render() {
		const {count} = this.state;
		return (
			<div> 
				<h3>RouteComponePage</h3> 
				<button onClick={() => {
					this.setState({count: count + 1});
 				}}>
 				click change count {count}
				</button> 
				<Router>
					<Route render={() => <FunctionChildcount={count} />} />
	 				<Route children={() => <FunctionChildcount={count} />} />
				</Router>
			</div>
 );
 }
}
class Child extends Component {
componentDidMount() {
console.log("componentDidMount"); //sy-log
 }
componentWillUnmount() {
console.log("componentWillUnmount"); //sylog
 }
render() {
return <div>child-{this.props.count}</div>;
 }
}
function FunctionChild(props) {
	useEffect(() => {
		return () => {
			console.log("WillUnmount"); //sy-log
 		};
 }, []);
return <div>child-{props.count}</div>; }

使⽤Router

动态路由

使⽤:id的形式定义动态路由

定义路由

<Route path="/search/:id" component={Search} />

添加导航链接

<Link to={"/search/" + searchId}>搜索</Link>

创建Search组件并获取参数

import React, { Component } from "react";
import { BrowserRouter, Link, Route } from "react-router-dom";
import HomePage from "./HomePage";
import UserPage from "./UserPage";
function Search({ match, history, location }) {
	const { id } = match.params;
	return (
		<div> 
			<h1>Search: {id}</h1>
		</div>
 );
}
export default class RouterPage extends

Component {
	render() {
	const searchId = "1234";
	return (
		<div> 
			<h1>RouterPage</h1> 
			<BrowserRouter> 
				<nav> 
					<Link to="/">⾸⻚</Link> 
					<Link to="/user">⽤户中⼼</Link> <Link to={"/search/" + searchId}>搜 索</Link>
				</nav>
 {/* 根路由要添加exact,实现精确匹配 */} 
 				<Route exact path="/" component= {HomePage}/>
				<Route path="/user" component= {UserPage} />
				<Route path="/search/:id" component= {SearchComponent} />
			</BrowserRouter>
		</div>
 );
 }}

嵌套路由

Route组件嵌套在其他⻚⾯组件中就产⽣了嵌套关系。

修改上面的组件Search,添加新增和详情:

function DetailComponent(props) {
return <div>DetailComponent</div>; }
function SearchComponent(props) {
	console.log("props", props); //sy-log
	const {id} = props.match.params;
	return (
		<div> 
			<h3>SearchComponent</h3> 
			<p>{id}</p> 
			<Link to={"/search/" + id + "/detail"}>详 情</Link> 
				<Route path="/search/:id/detail" component={DetailComponent} />
		</div>
 );
}