React-4.2 React-router 小案例

react-router路由小案例 -- 点击不同的类型及页码,请求和显示相应内容

  • src
    • 1. app.js
    • 2. index.js
    • 3. index.css
    • 4. http.js 请求数据
    • 5. router文件夹
      • router.js
    • 6. component文件夹
      • 6.1 Nav.js 顶部导航
      • 6.2 inner.js 列表显示区
        • list.js 中间内容显示区
        • footer.js 底部页码区
      • 6.3 page404.js

src

React-4.2 React-router 小案例_第1张图片

1. app.js

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;

2. index.js

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')
);

3. index.css

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;
}

4. http.js 请求数据

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;

5. router文件夹

router.js

一个一个写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};

6. component文件夹

6.1 Nav.js 顶部导航

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;

6.2 inner.js 列表显示区

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>
    )

}

list.js 中间内容显示区

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>
    )

}

footer.js 底部页码区

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>)

}

6.3 page404.js

import React from "react";

export default function Page404(){
     
    return <div>页面飞走了</div>
}

你可能感兴趣的:(React.js,react,js,reactjs,react路由)