long long ago,页面之间是通过超链接进行跳转的。跳转的时候会先从服务器请求一个新的页面,当页面下载到本地缓存了再跳转到新的页面上。
react是一个SPA,它只有一个index.html,所以react的跳转是组件之间的跳转,使用路由的方式实现。使用路由,第一次加载的时候就把所有的组件加载到内存里面了,然后根据路由规则和页面url在页面上动态显示相应的组件。
知识点
- 路由
- 路由传参
- 使用useState来管理组件数据
- 使用useEffect来管理方法执行
- fetch查询后台数据
开始
我们以典型的网站布局作为案例,顶部是导航(主页/关于我们/新闻列表),下面是内容区域。

graph TB
App-->Nav
App-->Content
Content-->Home
Content-->About
Content-->NewsList
- App.js
import React from "react";
import NavBar from "./component/navBar";
const App = () => {
return (
<React.Fragment>
<NavBar />
<Content />
</React.Fragment>
);
};
const Content = () => {
return (
<div className="container">
<Home />
<About />
<NewsList />
</div>
);
};
const Home = () => {
return <p>主页</p>;
};
const About = () => {
return <p>关于我们</p>;
};
const NewsList = () => {
return <p>新闻列表</p>;
};
export default App;
- navBar.jsx
import React from "react";
const NavBar = () => {
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
<div className="container">
<a className="navbar-brand" href="#">
XX网
</a>
<div className="collapse navbar-collapse">
<ul className="navbar-nav mr-auto">
<li className="nav-item">
<a className="nav-link" href="#">
主页
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">
关于我们
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">
新闻列表
</a>
</li>
</ul>
</div>
</div>
</nav>
);
};
export default NavBar;
一开始我们把Home组件,About组件,NewsList组件都展示在了中间区域,下一步我们希望根据url的不同来在内容区域渲染不同的组件
安装react-router-dom
npm i react-router-dom
使用路由
- App.js
import React from "react";
import NavBar from "./component/navBar";
import { BrowserRouter, Switch, Route } from "react-router-dom";
const App = () => {
return (
<BrowserRouter>
<NavBar />
<Content />
</BrowserRouter>
);
};
const Content = () => {
return (
<div className="container">
<Switch>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/newsList" component={NewsList} />
</Switch>
</div>
);
};
const Home = () => {
return <p>主页</p>;
};
const About = () => {
return <p>关于我们</p>;
};
const NewsList = () => {
return <p>新闻列表</p>;
};
export default App;
- navBar.jsx
import React from "react";
import { Link } from "react-router-dom";
const NavBar = () => {
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
<div className="container">
<a className="navbar-brand" href="#">
XX网
</a>
<div className="collapse navbar-collapse">
<ul className="navbar-nav mr-auto">
<li className="nav-item">
<Link className="nav-link" to="/">
主页
</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/about">
关于我们
</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/newsList">
新闻列表
</Link>
</li>
</ul>
</div>
</div>
</nav>
);
};
export default NavBar;
BrowserRouter代表路由代码的区域(所有Route,Switch,Link都得在它下面)
Route代表路由规则,path指代url路径,component指代路由到的组件,exact【可选】表示url严格匹配
Switch顾名思义,就是取第一个匹配上的路由,之后的不再匹配
Link就是路由里面的路由跳转,类似于a标签,to类似于a标签的href

路由间传递参数
这里我们拿新闻列表组件举例。一般的新闻网站一开始会列出最新的新闻,点击新闻进入新闻详情页面。我们使用json-server来模拟新闻api。
react通过http请求取数据,然后渲染到页面上。
点击某一则新闻,进入新闻详情面,并将新闻id传递到新闻详情面。
新闻详情面根据传递过来的新闻id,请求后台数据,并渲染到页面上。
json-server的用法见json-server-零代码构建后台rest api服务
- data.json
{
"news":[
{"id":1,"title":"Bootstrap","author":"张三","date":"2019-06-25","content":"Bootstrap 优站精选频道收集了众多基于 Bootstrap 构建、设计精美的、有创意的网站。"},
{"id":2,"title":"Webpack","author":"李四","date":"2019-06-24","content":"Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。"},
{"id":3,"title":"React","author":"王二","date":"2019-06-23","content":"React 起源于 Facebook 的内部项目,是一个用于构建用户界面的 JavaScript 库。"},
{"id":4,"title":"TypeScript","author":"麻子","date":"2019-06-22","content":"TypeScript 是由微软开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。"},
{"id":5,"title":"jQuery","author":"tom","date":"2019-06-21","content":"根据最新的 jQuery 1.11.x 和 2.1.x 版本翻译的 jQuery API 中文文档/手册"},
{"id":6,"title":"Next","author":"jerry","date":"2019-06-20","content":"Next.js 是一个轻量级的 React 服务端渲染应用框架。"}
]
}
json-server -w data.json -p 4000
此处我们使用json-server提供的2个api
- 查询全部新闻:http://localhost:4000/news
- 查询单个新闻:http://localhost:4000/news/1
- newsList.jsx
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
const NewsList = () => {
//声明newsList状态
const [newsList, setNewsList] = useState([]);
//页面渲染查询后台数据
useEffect(() => {
fetchNewsList();
}, []);
//定义后台数据查询方法
const fetchNewsList = async () => {
const response = await fetch(`http://localhost:4000/news`);
const data = await response.json();
setNewsList(data);
};
return (
<ul className="list-group mt-4">
{newsList.map(news => (
<li className="list-group-item" key={news.id}>
<Link to={`/newsList/${news.id}`}>{news.title}</Link>
</li>
))}
</ul>
);
};
export default NewsList;
- newsDetail.jsx
import React, { useEffect, useState } from "react";
const NewsDetail = ({ match }) => {
//获取路径参数新闻id
const newsId = match.params.id;
//声明news状态和设置新闻的方法
const [news, setNews] = useState({});
//定义获取后台新闻的方法
const fetchNews = async () => {
const response = await fetch(`http://localhost:4000/news/${newsId}`);
const data = await response.json();
setNews(data);
};
//页面加载后台查询
useEffect(() => {
fetchNews();
});
return (
<div class="card mt-4" style={{ width: "100%" }}>
<div class="card-body">
<h5 class="card-title">{news.title}</h5>
<h6 class="card-subtitle mb-2 text-muted">
作者:{news.author}/发布时间:{news.date}
</h6>
<p class="card-text">{news.content}</p>
</div>
</div>
);
};
export default NewsDetail;
组件传递参数,通过props.match来拿到相关参数对象,此处我们是路径传参
- App.js
增加了新组建NewsDetail,需要增加新的路由规则
import React from "react";
import NavBar from "./component/navBar";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import NewsList from "./component/newsList";
import NewsDetail from "./component/newsDetail";
const App = () => {
return (
<BrowserRouter>
<NavBar />
<Content />
</BrowserRouter>
);
};
const Content = () => {
return (
<div className="container">
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
<Route path="/newsList" exact component={NewsList} />
<Route path="/newsList/:id" component={NewsDetail} />
</Switch>
</div>
);
};
const Home = () => {
return <p>主页</p>;
};
const About = () => {
return <p>关于我们</p>;
};
export default App;
注意此处newsList组件的路由规则增加了exact

网友评论