《CMS后台系统》项目实战 详细分解(五)

226 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

下拉菜单

引入用户头像

// 引入useState
import React, {useEffect,useState} from 'react'

// 引入默认头像图片
import defaultAvatar from '../assets/defaultAvatar.jpg'

// 使用useState
const [avatar,setAvatar] = useState(defaultAvatar)

// 插入图片
 <img src={avatar} className="avatar" alt='' />
 

image.png

添加默认用户名

// 使用useState
const [username,setUsername] = useState('游客')

<span>{username}</span>

注意:添加key!

const menu = (
        <Menu>
          <Menu.Item key={1}>
            修改资料
          </Menu.Item>
          <Menu.Divider />
          <Menu.Item key ={2}>>
            退出登录
          </Menu.Item>

        </Menu>
      );
  • 实现效果图

image.png

修改样式

在base.less 下书写样式

image.png

    .right {
        height: 40px;
        .avatar {
            width: 40px;
            height: 40px;
            border-radius: 50%;
        }
        span {
            margin-left: 10px;
            margin-right: 10px;
        }
    }
  • 实现效果图

image.png

修改下拉菜单边距

  • 原样

image.png

在base.less中书写对应a标签的属性

        .ant-dropdown-link{
            height: 60px;
            display: block;
            color: #333;
            &:hover{
                color: #1890ff;
            }
        }
  • 实现效果图

image.png

  • 使用useEffect

在Application中会找到请求存储的数据。

image.png

我们将使用这些数据替代默认的用户名和用户头像。

  • 用户名
    // 模拟componentDidMount
  useEffect(()=>{
    let username1 = localStorage.getItem('username')
    if(username1){
      setUsername(username1)
    }
  },[])
  • 实现效果图

image.png

  • 用户头像
    // 模拟componentDidMount
  useEffect(()=>{
    let username1 = localStorage.getItem('username')
    let avatar1 = localStorage.getItem('avatar')
    if(username1) {
      setUsername(username1)
    }
    if(avatar1) {
      setAvatar('http://47.93.114.103:6688/' + avatar1)
    }
  },[])

注意:传入图片时,记得添加路径。

  • 实现效果图

image.png

退出登录

不可以直接使用Link,进行跳转,因为在Application中数据依然存在。退出时必须清除数据。

import {Link, useNavigate} from 'react-router-dom'

const navigate = useNavigate()
    
// 退出登录
  const logout = () => {
    message.success('退出成功,即将返回登录页')
    localStorage.clear();   // 清除localStorage中的数据
    setTimeout(() => navigate('/login'), 1500)
}

<Link to="/login"  onClick={logout} >退出登录</Link>
  • 实现效果

image.png

侧边栏布局

  • 创建Aside组件

image.png

  • 修改App组件

image.png

const App = () => {

const {Sider, Content } = Layout;

    return (
        <Layout id='app'>
            <Header/>
        <Layout>
        <Aside />
          <Content>
          <div>
            <Outlet/>   
          </div>
          </Content>
        </Layout>
        <footer>Footer</footer>
      </Layout>
    );
}

export default App;
  • 书写Aside组件

Menu

传送门

ant.design/components/…

Aside组件

import React from 'react'
import { Menu } from 'antd';
import { ReadOutlined, EditOutlined, DatabaseOutlined } from '@ant-design/icons';

export default function Aside() {

  
  const handleClick = e => {
    console.log('click',e)
  };


  return (
    <Menu
        onClick={handleClick}
        style={{ width: 180 }}
        mode="inline"
        theme="dark" // 黑色主题
    >
      <Menu.Item key="3">Option 3</Menu.Item>
      <Menu.Item key="4">Option 4</Menu.Item>
      </Menu>
  )
}

App组件

import Aside from './components/Aside'
import React from 'react';
import "./assets/base.less"
import { Outlet } from 'react-router-dom';
import { Layout } from 'antd';
import Header from './components/Header'
import Aside from './components/Aside'

const App = () => {

const {Content } = Layout;

    return (
        <Layout id='app'>
            <Header/>
        <Layout>
        <Aside />
          <Content>
          <div>
            <Outlet/>   
          </div>
          </Content>
        </Layout>
        <footer>Footer</footer>
      </Layout>
    );
}

export default App;

  • 实现效果图

image.png

  • 为Aside设置类名
    <Menu
        onClick={handleClick}
        style={{ width: 180 }}
        mode="inline"
        className='aside'
        theme="dark" // 黑色主题
    >
      <Menu.Item key="3">Option 3</Menu.Item>
      <Menu.Item key="4">Option 4</Menu.Item>
      </Menu>
  • App组件内设置属性名
import React from 'react';
import "./assets/base.less"
import { Outlet } from 'react-router-dom';
import { Layout } from 'antd';
import Header from './components/Header'
import Aside from './components/Aside'

function App() {
    return (
        <Layout id='app'>
            <Header/>
        <div className='container'>
         <Aside />       
        <div className='container_box'>
            <div>
              <Outlet/>   
            </div>
        </div>
      </div>  
        <footer>Footer</footer>
      </Layout>
    );
}

export default App;
  • base.less 书写属性
.container{
    display: flex;
    // justify-content: space-between;
    .aside{
        height: calc(100vh - 140px);
    }
    .container_box{
        flex: 1;
        box-sizing: border-box;
        padding: 20px;
        display: flex;
        flex-direction: column;
        .container_content{
            height: calc(100vh - 210px);
            overflow: hidden;
        }
    }
}

-实现效果

image.png

添加图标

      <Menu.Item key="1"><ReadOutlined /> 查看文章列表</Menu.Item>
      <Menu.Item key="2"><EditOutlined /> 文章编辑</Menu.Item>
      <Menu.Item key="3"><DatabaseOutlined /> 修改资料</Menu.Item>

在文字和图标紧凑在一起的时候,我们需要可以敲进一个空格来使得排版更加美观。

  • 实现效果图

image.png