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

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

下拉菜单

引入用户头像

// 引入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='' />
复制代码


b1775815e7074d7088b909f0eb02ac38_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.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>
      );
复制代码


  • 实现效果图

dfd50450616e433986fa3b09a351a6c1_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


修改样式

在base.less 下书写样式

756274a7984f4c6fb99d02d73549fb8b_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


.right {
        height: 40px;
        .avatar {
            width: 40px;
            height: 40px;
            border-radius: 50%;
        }
        span {
            margin-left: 10px;
            margin-right: 10px;
        }
    }
复制代码


  • 实现效果图

ec8671d5396a44ae83c7d3cd218d263f_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


修改下拉菜单边距

  • 原样

4d9db82a5178425c95c2940bd1a0d112_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


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

.ant-dropdown-link{
            height: 60px;
            display: block;
            color: #333;
            &:hover{
                color: #1890ff;
            }
        }
复制代码


  • 实现效果图

7348e1a89a7c425696f6c65003f88177_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


  • 使用useEffect

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

3ec3085a9ece4157932de45ee00bc7d0_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


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

  • 用户名
// 模拟componentDidMount
  useEffect(()=>{
    let username1 = localStorage.getItem('username')
    if(username1){
      setUsername(username1)
    }
  },[])
复制代码


  • 实现效果图

166f13e3cc40446284f0898264f30e46_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.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)
    }
  },[])
复制代码


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

  • 实现效果图

c49fb65f310d4420a6ac5bee2ffa7de2_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.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>
复制代码


  • 实现效果

db95854b91bb42408a379b940eb2aea1_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


侧边栏布局

  • 创建Aside组件

8a9f504df08d41198cd70c4bf492340f_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


  • 修改App组件

a4a519dce04e484f90cdee701ca765d3_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.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;
复制代码


  • 实现效果图

c0f468d878a04e6c8cab14546081d206_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.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;
        }
    }
}
复制代码


-实现效果

5c88f13faa4245c38e3ef4181ee2a07c_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


添加图标

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


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


  • 实现效果图

bef0713a1ca4460ca42d6b116597f618_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png



目录
相关文章
|
数据库
【自然框架】CMS之数据库设计
    在园子里也混了三年多,随笔200多,一开始只是想把自己的经验写一下,后来呢弄出来了一个“自然框架”,主要精力就放在了介绍自然框架的思路上面了。随笔多了就发现一个问题:有点乱。虽然博客有分组,但是只支持一级分组,不支持n级的。
1578 0
|
2月前
|
消息中间件 算法 前端开发
京东面试:说说CMS工作原理?
京东面试:说说CMS工作原理?
38 2
|
小程序 数据可视化 数据库
云开发(微信-小程序)笔记(十七)---- cms(内容管理)及案例
云开发(微信-小程序)笔记(十七)---- cms(内容管理)及案例
506 0
|
存储 缓存 前端开发
项目实战典型案例13——学情页面逻辑问题
项目实战典型案例13——学情页面逻辑问题
59 0
|
存储 缓存 前端开发
【项目实战典型案例】13.学情页面逻辑问题
【项目实战典型案例】13.学情页面逻辑问题
|
Java
项目实战典型案例11——生产环境重大事故
项目实战典型案例11——生产环境重大事故
89 0
|
数据库 Nacos
【项目实战典型案例】08.用户成为设计者的正例
【项目实战典型案例】08.用户成为设计者的正例
【项目实战典型案例】14.课程推送页面整理-增加定时功能
【项目实战典型案例】14.课程推送页面整理-增加定时功能
【项目实战典型案例】11.生产环境的重大事故
【项目实战典型案例】11.生产环境的重大事故
|
前端开发 API
《CMS后台系统》项目实战 详细分解(九)
《CMS后台系统》项目实战 详细分解(九)
104 0
《CMS后台系统》项目实战 详细分解(九)