【React】极客园案例实践-Layout模块

前情提要-项目搭建和登录模块完成

Layout模块

3、Layout模块

3-1 本结构和样式reset

结构创建

pages/Layout/index.jsx

jsx 复制代码
import { Layout, Menu, Popconfirm } from 'antd'
import {
  HomeOutlined,
  DiffOutlined,
  EditOutlined,
  LogoutOutlined,
} from '@ant-design/icons'
import './index.scss'

const { Header, Sider } = Layout

const items = [
  {
    label: '首页',
    key: '1',
    icon: <HomeOutlined />,
  },
  {
    label: '文章管理',
    key: '2',
    icon: <DiffOutlined />,
  },
  {
    label: '创建文章',
    key: '3',
    icon: <EditOutlined />,
  },
]

const GeekLayout = () => {
  return (
    <Layout>
      <Header className="header">
        <div className="logo" />
        <div className="user-info">
          <span className="user-name">柴柴老师</span>
          <span className="user-logout">
            <Popconfirm title="是否确认退出?" okText="退出" cancelText="取消">
              <LogoutOutlined /> 退出
            </Popconfirm>
          </span>
        </div>
      </Header>
      <Layout>
        <Sider width={200} className="site-layout-background">
          <Menu
            mode="inline"
            theme="dark"
            defaultSelectedKeys={['1']}
            items={items}
            style={{ height: '100%', borderRight: 0 }}></Menu>
        </Sider>
        <Layout className="layout-content" style={{ padding: 20 }}>
          内容
        </Layout>
      </Layout>
    </Layout>
  )
}
export default GeekLayout

pages/Layout/index.scss

bash 复制代码
.ant-layout {
  height: 100%;
}

.header {
  padding: 0;
}

.logo {
  width: 200px;
  height: 60px;
  background: url('@/assets/logo.png') no-repeat center / 160px auto;
}

.layout-content {
  overflow-y: auto;
}

.user-info {
  position: absolute;
  right: 0;
  top: 0;
  padding-right: 20px;
  color: #fff;

  .user-name {
    margin-right: 20px;
  }

  .user-logout {
    display: inline-block;
    cursor: pointer;
  }
}

.ant-layout-header {
  padding: 0 !important;
}

样式初始化

bash 复制代码
npm install normalize.css

main.jsx中引入

index.scss

css 复制代码
html,
body {
  margin: 0;
  height: 100%;
}

#root {
  height: 100%;
}

3-2 二级路由配置

使用步骤

  1. 在 pages 目录中,分别创建:Home(数据概览)/Article(内容管理)/Publish(发布文章)页面文件夹
  2. 分别在三个文件夹中创建 index.jsx 并创建基础组件后导出
  3. router/index.js 中配置嵌套子路由,在Layout中配置二级路由出口
  4. 使用 Link 修改左侧菜单内容,与子路由规则匹配实现路由切换


    代码实现

pages/Home/index.jsx

jsx 复制代码
const Home = () => {
  return <div>Home</div>
}
export default Home

pages/Article/index.jsx

jsx 复制代码
const Article = () => {
  return <div>Article</div>
}
export default Article

pages/Publish/index.jsx

jsx 复制代码
const Publish = () => {
  return <div>Publish</div>
}
export default Publish

router/index.jsx

jsx 复制代码
import { createBrowserRouter } from 'react-router-dom'

import Login from '@/pages/Login'
import Layout from '@/pages/Layout'
import Publish from '@/pages/Publish'
import Article from '@/pages/Article'
import Home from '@/pages/Home'
import { AuthRoute } from '@/components/Auth'

const router = createBrowserRouter([
  {
    path: '/',
    element: (
      <AuthRoute>
        <Layout />
      </AuthRoute>
    ),
    children: [
      {
        index: true,
        element: <Home />,
      },
      {
        path: 'article',
        element: <Article />,
      },
      {
        path: 'publish',
        element: <Publish />,
      },
    ],
  },
  {
    path: '/login',
    element: <Login />,
  },
])

export default router

配置二级路由出口

3-3 路由菜单点击交互实现

点击菜单跳转路由

点击左侧菜单可以跳转到对应的目标路由



提交-09点击菜单跳转路由

根据当前路径菜单反向高亮

实现效果:页面在刷新时可以根据当前的路由路径让对应的左侧菜单高亮显示

思路分析

  1. 获取当前url上的路由路径
  2. 找到菜单组件负责高亮的属性,绑定当前的路由路径

使用一个钩子函数useLocation,用于在函数组件中获取当前页面的「路由位置信息」(包括 URL 路径、查询参数、hash、状态等),获取当前的key

使用这个属性selectedKeys

提交-10layout-根据路由路径高亮菜单

3-4 展示个人信息

用户的信息通常很有可能在多个组件中都需要共享使用,同样应该放到Redux中维护

实现步骤

  1. 在Redux的store中编写获取用户信息的相关逻辑
  2. 在Layout组件中触发action的执行
  3. 在Layout组件使用使用store中的数据进行用户名的渲染

代码实现
store/userStore.jsx

pages/Layout/index.js

测试get请求是否成功

提交-11layout获取渲染用户信息

3-5 退出登录实现

实现步骤

  1. 为气泡确认框添加确认回调事件
  2. store/userStore.js 中新增退出登录的action函数,在其中删除token
  3. 在回调事件中,调用userStore中的退出action
  4. 清除用户信息,返回登录页面

代码实现
store/modules/user.jsx

pages/Layout/index.jsx

调用Popconfirm 组件的事件属性onConfirm,在onConfirm中编写退出登录的函数

提交-12layout退出登录实现

3-6 处理Token失效

业务背景:如果用户一段时间不做任何操作,到时之后应该清除所有过期用户信息跳回到登录

通常在Token失效之后再去请求接口,后端会返回401状态码,前端可以监控这个状态做后续的操作


根据401状态码做操作
utils/request.jsx

提交-13token的失效处理

3-7 首页Home图表展示

echarts中文文档

bash 复制代码
// 导入
import * as echarts from 'echarts';
// 1.获取渲染图标的Dom节点
var chartDom = document.getElementById('main');
// 2.图标初始化生成图表实例对象
var myChart = echarts.init(chartDom);
// 3.准备图表参数
var option = {
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [120, 200, 150, 80, 70, 110, 130],
      type: 'bar'
    }
  ]
};
// 4.使用图表参数完成图表的渲染
option && myChart.setOption(option);

图表基础Demo实现

图表类业务渲染,我们可以通过下面的顺序来实现

  1. 跑通基础DEMO
  2. 按照实际业务需求进行修改

安装echarts

bash 复制代码
npm i echarts

实现基础Demo

ECharts 图表节点必须设置宽高
pages/Home/index.jsx

提交-14echarts图表初始化

组件封装


提交-15echarts组件封装

3-8 API模块封装

把项目中的所有接口按照业务模块以函数的形式统一封装到apis模块中

apis/user.jsx

jsx 复制代码
// 封装用户相关的所有请求

import { request } from "@/utils"

// 1.登录请求
export function loginAPI(formData) {
  // axios规范写法
  return request({
    url: '/authorizations',
    method: 'POST',
    data: formData
  })
}

// 2.获取用户相关信息
export function getProfilrAPI() {
  return request({
    url: '/user/profile',
    method: 'GET'
  })
}

store/modules/user,jsx

提交-16封装apis模块

相关推荐
辛-夷41 分钟前
vue高频面试题
前端·vue.js
IT小哥哥呀43 分钟前
《纯前端实现 Excel 导入导出:基于 SheetJS 的完整实战》
前端·excel
文心快码BaiduComate1 小时前
CCF程序员大会码力全开:AI加速营决赛入围名单揭晓,12月6日大理见!
前端·百度·程序员
vivo互联网技术1 小时前
从不足到精进:H5即开并行加载方案的演进之路
前端·h5·webview·客户端·大前端
我命由我123451 小时前
微信小程序 - 内容弹出框实现(Vant Weapp 实现、原生实现)
开发语言·前端·javascript·微信小程序·小程序·前端框架·js
裴嘉靖1 小时前
uniapp做的APP和安卓苹果做的什么区别
前端
申阳1 小时前
Day 20:开源个人项目时的一些注意事项
前端·后端·程序员
天蓝色的鱼鱼1 小时前
大文件上传实战:基于Express、分片、Web Worker与压缩的完整方案
前端·node.js
500佰1 小时前
解读NotebookLM基于AI的PTT生成 程序化处理方法
前端·google·程序员