import React from 'react';
import Nav from './component/Nav';
// import { Switch } from 'react-router-dom';
import {
Switch,Route } from 'react-router-dom';
import {
router } from "./router/router";
// import Page404 from '../component/page404';
function App() {
return (
<div className="wrap">
{
/* 配置头部路由跳转 */}
<Nav></Nav>
<Switch>
{
/* 循环配置路由,具体看router.js的配置内容 */}
{
router.map((item,index)=>{
return (<Route
key={
index}
path={
item.path}
render={
item.render}
exact={
item.exact}
>
</Route>)
})
}
{
/* 回忆原始写法:
{
return
}}/>
*/ }
</Switch>
</div>
);
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import "./index.css";
import {
BrowserRouter} from 'react-router-dom';
import App from './App';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
text-decoration: none;
}
.wrap {
margin: 0 auto;
width: 800px;
padding-top: 20px;
}
.nav {
display: flex;
border-bottom: 1px solid #000;
height: 40px;
}
.nav a {
flex: 1;
font: 14px/38px "宋体";
text-align: center;
padding: 1px 1px 0;
color: #000;
height: 40px;
margin-bottom: -1px;
}
.nav a.active {
background: #fff;
color: red;
padding: 0;
border: 1px solid #000;
border-bottom: none;
}
.pageNav {
display: flex;
margin-top: 10px;
border-top: 1px solid #000;
padding-top: 5px;
justify-content: center;
}
.pageNav a,
.pageNav span {
margin: 0 3px;
width: 28px;
font: 14px/30px "宋体";
text-align: center;
color: #000;
border: 1px solid red;
color: red;
}
.pageNav span {
padding: 1px;
border: none;
color: #000;
}
import Axios from "axios"
const http = Axios.create({
baseURL:"https://cnodejs.org/api/v1"
})
function getData(type,page){
return http.get(`/topics?page=${
page}&tab=${
type}&limit=20`);
}
export default getData;
一个一个写NavLink或者Link较繁琐,且不利于后期修改维护,所以把数据全部提取出来到router.js里,然后从router.js里遍历数据
import React from "react";
import {
Redirect} from "react-router-dom";
import Inner from "../component/inner";
import Page404 from "../component/page404";
const types = ["all","good","share","dev","ask","job"]
const nav = [
{
url: "/all",
exact: true,
txt: "全部"
},{
url: "/good",
exact: true,
txt: "精华"
},{
url: "/share",
exact: true,
txt: "分享"
},{
url: "/ask",
exact: true,
txt: "问答"
},{
url: "/job",
exact: true,
txt: "招聘"
},{
url: "/dev",
exact: true,
txt: "客户端测试"
}
];
const router = [
// 1.重定向
{
path:"/",
exact: true,
render:(props)=>{
return <Redirect to="/all" />;
}
},
// 2.type和page,也即等于改变页码时
{
path: "/:type/:page",
exact: true,
render:(props)=>{
console.log(props);
let {
type,page} = props.match.params; //接收动态路由传来的参数
// 判断是否 已有
if(types.includes(type)&&page>0){
return <Inner {
...props} />;
}
return <Page404 />; //错误路径的判断
}
},
// 3.只点击变换type类型时
{
path: "/:type",
exact: true,
render:(props)=>{
let {
type} = props.match.params;
if(types.includes(type)){
return <Redirect to={
`/${
type}/${
JSON.parse(sessionStorage.getItem(type)) || 1}`} />;
}
return <Page404 />;
}
},
// 4.没有匹配路由时
{
path: "",
exact: false,
render:()=>{
return <Page404 />;
}
}
];
export {
router,nav};
import React from "react";
import {
NavLink, useLocation} from "react-router-dom";
import {
nav } from "../router/router";
// 循环创建NavLink,配置头部路由跳转
function Nav(){
let {
pathname} = useLocation();
// console.log(pathname);
pathname = pathname.split("/");
// console.log(pathname); //["" "job" "1"]
return (
<nav className="nav">
{
nav.map((item,index)=>{
let {
url} = item;
url = url.split("/")
return(<NavLink
to={
item.url}
key={
index}
exact={
item.exact}
activeClassName="active"
isActive={
()=>{
return url[1] === pathname[1]
}}
>{
item.txt}</NavLink>)
})
}
</nav>
);
}
export default Nav;
import React from "react"
import List from "./list"
import {
useState,useEffect,Fragment } from "react"
import getData from "../http"
import {
useParams } from "react-router-dom"
import Footer from "./footer"
export default function Inner(){
let {
type,page} = useParams(); //动态路由
let [data,setdata] = useState([]);
let [isLoad,setLoad] = useState(false);
useEffect(() => {
if(!isLoad){
getData(type,page).then((res)=>{
console.log(res);
// console.log(type);
// console.log(page);
setdata(res.data.data); //使data更新为新获取的值,从而渲染改变页面
setLoad(true); //获取完毕后,把isLoad变为true,则不再重新去获取值
});
}
}, [isLoad])
useEffect(() => {
setLoad(false)
// 页码存储功能 -- 存 *** 在切换导航或者切换页码时进行存储,临时存储sessionStorage
sessionStorage.setItem(type,JSON.stringify(page))
}, [type,page]) //随着type,page的变化,而去改变isLoad的布尔值,从而操控是否去获取相应的新数据
return(
<div>
{
(!isLoad) ? (<div>数据请求中</div>)
: (<Fragment>
<List data={
data}></List>
<Footer />
</Fragment>)
}
</div>
)
}
import React from "react"
export default function List(props){
let {
data} = props;
// console.log(data);//Array(20) 是有id值,title等等值
return(
<ul>
{
data.map((item,index)=>{
return(<li
key={
item.id}
>
{
item.title}
</li>)
})
}
</ul>
)
}
import React from "react"
import {
Link, useParams } from "react-router-dom";
export default function Footer(){
let {
type,page} = useParams();
// 页码长度
let pageLength = 10;
// 页码存储功能 -- 取 *** 在使用页码的位置取数据
let pageStart =JSON.parse(sessionStorage.getItem(type)) - 5 || page - 5; //减几都是自定义的,减5意思是点中的页码位置前面一直放5个按钮,pageStart在这里定义的是第一个页码的页数,
// 加一个安全判断
pageStart = pageStart<1 ? 1: pageStart;
pageStart--; // 先减一,因为下面循环遍历时需要逐步加1,但循环的第一个是不需要加的,所以这里先减1
return (<nav className="pageNav">
{
[...(".".repeat(pageLength))].map((item,index)=>{
pageStart++;
if(pageStart == page){
// 当增加到所对应按下的数据时,令返回一个span,从而通过css来区别样式
return <span key={
index}>{
pageStart}</span>
}else{
// 不相等——说明这个不是选中的页面,需要他是拥有跳转功能的Link标签,跳转时的地址就是我们接收的,只需要改变页码就可以了
return <Link key={
index} to={
`/${
type}/${
pageStart}`}>{
pageStart}</Link>
}
})
}
</nav>)
}
import React from "react";
export default function Page404(){
return <div>页面飞走了</div>
}