从0开始手把手教你做极客园项目(二)——首页功能实现

文章目录

  • 前言
    • 1.首页静态结构准备
    • 2.配置二级路由
    • 3.点击跳转路由
    • 4.菜单栏高光
    • 5.渲染用户信息
    • 6.退出登录功能
    • 7.设置token失效
    • 8.Home渲染图表数据
  • 总结


前言

上一篇文章中(从0开始手把手教你做极客园项目(一)——登录功能实现)详细讲解了登录功能,在登录跳转后就是首页,本文详细讲解跳转到首页的功能实现源码地址极客园github

1.首页静态结构准备

在Layout/index.tsx里参考antd的官方文档将首页的界面搭建,items表示首页右边三个导航栏的切换

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">zwb</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

对应的index.scss样式文件如下

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

同时安装normalize.css用于消除浏览器默认样式,在根目录下的index.tsx里引入,并且创建一个index.scss文件用于设置整个界面充满的样式

npm install normalize.css
import 'normalize.css'
import './index.scss'
html,
body {
  margin: 0;
  height: 100%;
}

#root {
  height: 100%;
}

从0开始手把手教你做极客园项目(二)——首页功能实现_第1张图片

2.配置二级路由

首先在pages里创建三个二级路由界面组件,分别表示首页,文章管理,创建文章的模块,rafce初始化组件,在router/index.tsx里添加layout路由的children表示二级路由,并在layout组件里导出二级路由

  {
        path: '/',
        element: <AuthRouter><Layout /></AuthRouter>,
        children: [
            {
                index:true,//默认二级路由
                element: <Home />
            }, 
            {
                path: 'article',
                element: <Article />
            }, 
            {
                path: 'publish',
                element: <Publish />
            }
        ]
    },
 <Layout className="layout-content" style={{ padding: 20 }}>
          <Outlet/>//二级路由出口
        </Layout>

从0开始手把手教你做极客园项目(二)——首页功能实现_第2张图片

3.点击跳转路由

实现跳转路由需要拿到当前点击的二级路由地址,可以将原来items里的key换成路径地址,然后通过添加点击函数获取到当前点击的key,利用navigate方法实现路由跳转

const items = [
  {
    label: '首页',
    key: '/',
    icon: <HomeOutlined />,
  },
  {
    label: '文章管理',
    key: '/article',
    icon: <DiffOutlined />,
  },
  {
    label: '创建文章',
    key: '/publish',
    icon: <EditOutlined />,
  },
]
const navigate=useNavigate()
<Menu
            mode="inline"
            theme="dark"
            defaultSelectedKeys={['1']}
            items={items}
            style={{ height: '100%', borderRight: 0 }}
            onClick={(router)=>{navigate(router.key)}}//点击跳转到相应key的路径路由
            ></Menu>

从0开始手把手教你做极客园项目(二)——首页功能实现_第3张图片

4.菜单栏高光

原来的菜单栏是只有点击的时候才会显示高光,但是在刷新界面的时候高光消失了,要解决这个问题可以使用useLocation获取到当前路径,在antd的Menu组件中增加一个selectedKeys这个属性,代表当前选中的值

const location=useLocation()
  const selected=location.pathname
<Menu
            mode="inline"
            theme="dark"
            selectedKeys={[selected]}
            items={items}
            style={{ height: '100%', borderRight: 0 }}
            onClick={(router)=>{navigate(router.key)}}
            ></Menu>

5.渲染用户信息

获取用户信息我们可以使用redux状态管理来对用户信息进行保存,在user.tsx文件中添加用户的状态和设置状态的函数,并通过一个异步方法获取后端的数据,在组件Layout/index.tsx中通过useEffect钩子函数在页面加载的时候就进行渲染

interface User {
    id: string;
    photo: string;
    name: string;
    mobile: string;
    gender: number;
    birthday: string;
    intro: string | null;
  }
const userStore = createSlice({
    name: 'user',
    initialState: {
        token: getToken() || '',
        user:{} as User
    },
    reducers: {
        setToken(state, action) {
            state.token = action.payload
            _setToken(action.payload)
        },
        setUser(state,action){
            state.user=action.payload
        }
    }
})
const fetchUser: () => (dispatch: Dispatch) => Promise<void> = () => {
    return async (dispatch: Dispatch) => {
      const res= await request.get('/user/profile')
      dispatch(setUser(res.data))
    }
}
const dispatch = useAppDispatch()
  useEffect(() => {
   dispatch(fetchUser())
  },[dispatch])

从0开始手把手教你做极客园项目(二)——首页功能实现_第4张图片
可以看见redux状态里已经有了后端取到的user对象,使用useAppSelector函数获取状态数据进行渲染

const name =useAppSelector(state=>state.user.user.name)
<span className="user-name">{name}</span>

从0开始手把手教你做极客园项目(二)——首页功能实现_第5张图片

6.退出登录功能

退出登录时,redux状态里关于所有用户的信息都要删除,并且localstorage里的token也要清除,所以在user.tsx的reducers中添加一个清除的函数

  exitUser(state){
            state.token=''
            state.user={} as User
            removeToken()
        }

在组建中绑定点击函数,点击函数调用清除的方法和跳转到登录界面

<Popconfirm title="是否确认退出?" okText="退出" cancelText="取消" onConfirm={onconfirm}>
              <LogoutOutlined /> 退出
            </Popconfirm>
const onconfirm=()=>{
    dispatch(exitUser())
    navigate('/login')
  }

从0开始手把手教你做极客园项目(二)——首页功能实现_第6张图片
从0开始手把手教你做极客园项目(二)——首页功能实现_第7张图片

7.设置token失效

用户在长时间未在网站做任何操作,且规定时间到达时,当前的token失效,token失效后,后端返回401状态码,而前端需要监控这个状态,在拦截器中监控401,清除token返回登录,在utils里的request.tsx里的响应拦截器添加清除和跳转界面以及刷新界面的操作

request.interceptors.response.use((response)=> {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response.data
  }, (error)=> {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    if(error.response.status===401){
      removeToken()
      router.navigate('/login')
      window.location.reload()
    }
    return Promise.reject(error)
})

可以手动模拟token失效,自行在localstorage里的token修改,然后手动按下刷新

8.Home渲染图表数据

安装echarts

npm install echarts 

封装一个柱状图组件,在Home里添加一个components文件夹,新建一个BarChart.tsx文件,文件当中引入echarts官网的柱状图模板,添加自己需要改的数据,使用useRef与节点进行绑定,

import * as echarts from 'echarts';
import { useEffect, useRef } from 'react';
interface Title{
  title:string
}
const BarChart = ({title}:Title) => {
  const chartRef = useRef(null)
  useEffect(() => {
    const chartDom = chartRef.current
    const myChart = echarts.init(chartDom);//初始化生成图表实例对象

    const option = {
      title: {
        text: title
      },
      xAxis: {
        type: 'category',
        data: ['vue', 'react', 'angular']
      },
      yAxis: {
        type: 'value'
      },
      series: [
        {
          data: [10, 40, 70],
          type: 'bar'
        }
      ]
    };

    option && myChart.setOption(option);
  })
  return (
    <div><div ref={chartRef} style={{ width: '500px', height: '400px' }}></div></div>
  )
}

export default BarChart

在父组件中index.tsx中调用组件,通过props传入title参数

<div style={{display:"flex",flexDirection:"row"}}>
      <BarChart title="三大框架满意度"/>
      <BarChart title="三大框架使用度"/>
      </div>

从0开始手把手教你做极客园项目(二)——首页功能实现_第8张图片

总结

本次实现了首页的基本功能,例如菜单跳转,二级路由,高亮显示以及图表数据显示(这里的图表数据有需要的话可以跟后端获取),再进行了优化例如token失效的情况,剩下的功能和优化会更新在后续,喜欢的小伙伴们点点关注点点赞,你们的支持就是我的动力

你可能感兴趣的:(echarts,ajax,typescript,react.js,前端)