【HM-React】08. Layout模塊

基本結構和樣式reset

結構創建

在這里插入圖片描述

實現步驟

  1. 打開 antd/Layout 布局組件文檔,找到示例:頂部-側邊布局-通欄
  2. 拷貝示例代碼到我們的 Layout 頁面中
  3. 分析并調整頁面布局

代碼實現
pages/Layout/index.js

import { Layout, Menu, Popconfirm } from 'antd'
import {HomeOutlined,DiffOutlined,EditOutlined,LogoutOutlined,
} from '@ant-design/icons'
import './index.scss'const { Header, Sider } = Layoutconst 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"><Menumode="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

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

樣式reset

npm install normalize.css
html,
body {margin: 0;height: 100%;
}#root {height: 100%;
}

二級路由配置

使用步驟

  1. 在 pages 目錄中,分別創建:Home(數據概覽)/Article(內容管理)/Publish(發布文章)頁面文件夾
  2. 分別在三個文件夾中創建 index.jsx 并創建基礎組件后導出
  3. router/index.js 中配置嵌套子路由,在Layout中配置二級路由出口
  4. 使用 Link 修改左側菜單內容,與子路由規則匹配實現路由切換

代碼實現
pages/Home/index.js

const Home = () => {return <div>Home</div>
}
export default Home

pages/Article/index.js

const Article = () => {return <div>Article</div>
}
export default Article

pages/Publish/index.js

const Publish = () => {return <div>Publish</div>
}
export default Publish

router/index.js

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

配置二級路由出口

<Layout className="layout-content" style={{ padding: 20 }}><Outlet />
</Layout>

路由菜單點擊交互實現

在這里插入圖片描述

點擊菜單跳轉路由

import { Outlet, useNavigate } from 'react-router-dom'const items = [{label: '首頁',key: '/',icon: <HomeOutlined />,},{label: '文章管理',key: '/article',icon: <DiffOutlined />,},{label: '創建文章',key: '/publish',icon: <EditOutlined />,},
]const GeekLayout = () => {const navigate = useNavigate()const menuClick = (route) => {navigate(route.key)}return (<Menumode="inline"theme="dark"selectedKeys={selectedKey}items={items}style={{ height: '100%', borderRight: 0 }}onClick={menuClick}/> )
}
export default GeekLayout

菜單反向高亮

const GeekLayout = () => {// 省略部分代碼const location = useLocation()const selectedKey = location.pathnamereturn (<Layout><Header className="header"><div className="logo" /><div className="user-info"><span className="user-name">{name}</span><span className="user-logout"><Popconfirm title="是否確認退出?" okText="退出" cancelText="取消"><LogoutOutlined /> 退出</Popconfirm></span></div></Header><Layout><Sider width={200} className="site-layout-background"><Menumode="inline"theme="dark"selectedKeys={selectedKey}items={items}style={{ height: '100%', borderRight: 0 }}onClick={menuClickHandler}></Menu></Sider><Layout className="layout-content" style={{ padding: 20 }}><Outlet /></Layout></Layout></Layout>)
}

展示個人信息

在這里插入圖片描述

實現步驟

  1. 在Redux的store中編寫獲取用戶信息的相關邏輯
  2. 在Layout組件中觸發action的執行
  3. 在Layout組件使用使用store中的數據進行用戶名的渲染

代碼實現
store/userStore.js

import { createSlice } from '@reduxjs/toolkit'
import { http } from '@/utils/request'
import { getToken, setToken } from '@/utils'
const userStore = createSlice({name: 'user',// 數據initialState: {token: getToken() || '',userInfo: {}},// 同步修改方法reducers: {setUserToken (state, action) {state.token = action.payload// 存入本地setToken(state.token)},setUserInfo (state, action) {state.userInfo = action.payload}}
})// 解構出actionCreater
const { setUserToken, setUserInfo } = userStore.actions// 獲取reducer函數
const userReducer = userStore.reducerconst fetchLogin = (loginForm) => {return async (dispatch) => {const res = await http.post('/authorizations', loginForm)dispatch(setUserToken(res.data.token))}
}const fetchUserInfo = () => {return async (dispatch) => {const res = await http.get('/user/profile')dispatch(setUserInfo(res.data))}
}export { fetchLogin, fetchUserInfo }export default userReducer

pages/Layout/index.js

// 省略部分代碼
import { fetchUserInfo } from '@/store/modules/user'
import { useDispatch, useSelector } from 'react-redux'const GeekLayout = () => {const dispatch = useDispatch()const name = useSelector(state => state.user.userInfo.name)useEffect(() => {dispatch(fetchUserInfo())}, [dispatch])return (<Layout><Header className="header"><div className="logo" /><div className="user-info"><span className="user-name">{name}</span><span className="user-logout"><Popconfirm title="是否確認退出?" okText="退出" cancelText="取消"><LogoutOutlined /> 退出</Popconfirm></span></div></Header><Layout><Sider width={200} className="site-layout-background"><Menumode="inline"theme="dark"defaultSelectedKeys={['1']}items={items}style={{ height: '100%', borderRight: 0 }}></Menu></Sider><Layout className="layout-content" style={{ padding: 20 }}><Outlet /></Layout></Layout></Layout>)
}
export default GeekLayout

退出登錄實現

在這里插入圖片描述

實現步驟

  1. 為氣泡確認框添加確認回調事件
  2. store/userStore.js 中新增退出登錄的action函數,在其中刪除token
  3. 在回調事件中,調用userStore中的退出action
  4. 清除用戶信息,返回登錄頁面

代碼實現
store/modules/user.js

import { createSlice } from '@reduxjs/toolkit'
import { http } from '@/utils/request'
import { clearToken, getToken, setToken } from '@/utils'
const userStore = createSlice({name: 'user',// 數據initialState: {token: getToken() || '',userInfo: {}},// 同步修改方法reducers: {setUserToken (state, action) {state.token = action.payload// 存入本地setToken(state.token)},setUserInfo (state, action) {state.userInfo = action.payload},clearUserInfo (state) {state.token = ''state.userInfo = {}clearToken()}}
})// 解構出actionCreater
const { setUserToken, setUserInfo, clearUserInfo } = userStore.actions// 獲取reducer函數
const userReducer = userStore.reducerexport { fetchLogin, fetchUserInfo, clearUserInfo }export default userReducer

pages/Layout/index.js

const GeekLayout = () => {// 退出登錄const loginOut = () => {dispatch(clearUserInfo())navigator('/login')}return (<Layout><Header className="header"><div className="logo" /><div className="user-info"><span className="user-name">{name}</span><span className="user-logout"><Popconfirm title="是否確認退出?" okText="退出" cancelText="取消" onConfirm={loginOut}><LogoutOutlined /> 退出</Popconfirm></span></div></Header><Layout><Sider width={200} className="site-layout-background"><Menumode="inline"theme="dark"selectedKeys={selectedKey}items={items}style={{ height: '100%', borderRight: 0 }}onClick={menuClickHandler}></Menu></Sider><Layout className="layout-content" style={{ padding: 20 }}><Outlet /></Layout></Layout></Layout>)
}

在這里插入圖片描述

處理Token失效

業務背景:如果用戶一段時間不做任何操作,到時之后應該清除所有過期用戶信息跳回到登錄

http.interceptors.response.use((response) => {// 2xx 范圍內的狀態碼都會觸發該函數。// 對響應數據做點什么return response.data
}, (error) => {// 超出 2xx 范圍的狀態碼都會觸發該函數。// 對響應錯誤做點什么console.dir(error)if (error.response.status === 401) {clearToken()router.navigate('/login')window.location.reload()}return Promise.reject(error)
})

首頁Home圖表展示

在這里插入圖片描述

圖表基礎Demo實現

圖表類業務渲染,我們可以通過下面的順序來實現

  1. 跑通基礎DEMO
  2. 按照實際業務需求進行修改

安裝echarts

npm i echarts

實現基礎Demo

import { useEffect, useRef } from 'react'
import * as echarts from 'echarts'const Home = () => {const chartRef = useRef(null)useEffect(() => {// 1. 生成實例const myChart = echarts.init(chartRef.current)// 2. 準備圖表參數const 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'}]}// 3. 渲染參數myChart.setOption(option)}, [])return (<div><div ref={chartRef} style={{ width: '400px', height: '300px' }} /></div >)
}export default Home

在這里插入圖片描述

組件封裝

基礎抽象

import { useRef, useEffect } from 'react'
import * as echarts from 'echarts'const BarChart = () => {const chartRef = useRef(null)useEffect(() => {// 1. 生成實例const myChart = echarts.init(chartRef.current)// 2. 準備圖表參數const 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'}]}// 3. 渲染參數myChart.setOption(option)}, [])return <div ref={chartRef} style={{ width: '400px', height: '300px' }}></div>
}export { BarChart }

抽象可變參數

import { useRef, useEffect } from 'react'
import * as echarts from 'echarts'const BarChart = ({ xData, sData, style = { width: '400px', height: '300px' } }) => {const chartRef = useRef(null)useEffect(() => {// 1. 生成實例const myChart = echarts.init(chartRef.current)// 2. 準備圖表參數const option = {xAxis: {type: 'category',data: xData},yAxis: {type: 'value'},series: [{data: sData,type: 'bar'}]}// 3. 渲染參數myChart.setOption(option)}, [sData, xData])return <div ref={chartRef} style={style}></div>
}export { BarChart }

import { BarChart } from './BarChart'const Home = () => {return (<div><BarChartxData={['Vue', 'React', 'Angular']}sData={[2000, 5000, 1000]} /><BarChartxData={['Vue', 'React', 'Angular']}sData={[200, 500, 100]}style={{ width: '500px', height: '400px' }} /></div >)
}export default Home

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/66003.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66003.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66003.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機視覺算法實戰——實時車輛檢測和分類(主頁有相關源碼)

?個人主頁歡迎您的訪問 ?期待您的三連 ? ?個人主頁歡迎您的訪問 ?期待您的三連 ? ?個人主頁歡迎您的訪問 ?期待您的三連? ? ?????????????????? 1. 領域介紹?? 實時車輛檢測和分類是計算機視覺中的一個重要應用領域&#xff0c;旨在從視頻流或…

使用 selenium-webdriver 開發 Web 自動 UI 測試程序

優缺點 優點 有時候有可能一個改動導致其他的地方的功能失去效果&#xff0c;這樣使用 Web 自動 UI 測試程序可以快速的檢查并定位問題&#xff0c;節省大量的人工驗證時間 缺點 增加了維護成本&#xff0c;如果功能更新過快或者技術更新過快&#xff0c;維護成本也會隨之提高…

性能測試工具Jmeter分布式運行

性能測試工具JMeter的分布式執行是一種用于增強壓力測試能力的技術方案&#xff0c;它允許用戶通過多臺機器來共同完成同一個測試計劃的執行。這種方式特別適用于需要模擬成百上千甚至上萬用戶并發訪問的情況&#xff0c;當單臺機器由于硬件資源&#xff08;如CPU、內存、網絡I…

彌散張量分析開源軟件 DSI Studio 簡體中文漢化版可以下載了

網址&#xff1a; (63條消息) DSIStudio簡體中文漢化版(2022年7月)-算法與數據結構文檔類資源-CSDN文庫

移動云自研云原生數據庫入圍國采!

近日&#xff0c;中央國家機關2024年度事務型數據庫軟件框架協議聯合征集采購項目產品名單正式公布&#xff0c;移動云自主研發的云原生數據庫產品順利入圍。這一成就不僅彰顯了移動云在數據庫領域深耕多年造就的領先技術優勢&#xff0c;更標志著國家權威評審機構對移動云在數…

在vscode中使用R-1

參考我的上一篇博客&#xff1a; https://blog.csdn.net/weixin_62528784/article/details/145092632?spm1001.2014.3001.5501 這篇內容實際上就是上一篇博客的后續承接&#xff0c;既然都在vscode的jupyter中使用R了&#xff0c;實際上其實也能夠直接在vscode中原生使用R的編…

【Block總結】掩碼窗口自注意力 (M-WSA)

摘要 論文鏈接&#xff1a;https://arxiv.org/pdf/2404.07846 論文標題&#xff1a;Transformer-Based Blind-Spot Network for Self-Supervised Image Denoising Masked Window-Based Self-Attention (M-WSA) 是一種新穎的自注意力機制&#xff0c;旨在解決傳統自注意力方法在…

【Linux】統信UOS服務器安裝MySQL8.0(RPM)

目錄 一、下載安裝包 二、安裝MySQL 2.1hive適配 2.2ranger適配 3.2DolphinScheduler適配 一、下載安裝包 官網下載安裝包&#xff1a;MySQL :: MySQL Downloads 選擇社區版本下載 點擊MySQL Community Server 選擇對應系統的MySQL版本號 統信1060a 操作系統對應 redhat8…

小白:react antd 搭建框架關于 RangePicker DatePicker 時間組件使用記錄 2

文章目錄 一、 關于 RangePicker 組件返回的moment 方法示例 一、 關于 RangePicker 組件返回的moment 方法示例 moment方法中日后開發有用的方法如下&#xff1a; form.getFieldsValue().date[0].weeksInWeekYear(),form.getFieldsValue().date[0].zoneName(), form.getFiel…

Jenkins簡單的安裝運行

一、下載 官網下載&#xff1a;https://www.jenkins.io/download/ 清華大學開源軟件鏡像站&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/jenkins/ 官網資料豐富&#xff0c;介紹了各種平臺安裝以及下載。安裝簡單&#xff0c;按照說明來就行。下面我介紹一個非常簡單的…

【CSS】HTML頁面定位CSS - position 屬性 relative 、absolute、fixed 、sticky

目錄 relative 相對定位 absolute 絕對定位 fixed 固定定位 sticky 粘性定位 position&#xff1a;relative 、absolute、fixed 、sticky &#xff08;四選一&#xff09; top&#xff1a;距離上面的像素 bottom&#xff1a;距離底部的像素 left&#xff1a;距離左邊的像素…

網絡安全 | WAF防護開通流程與技術原理詳解

關注&#xff1a;CodingTechWork 引言 隨著互聯網安全形勢的日益嚴峻&#xff0c;Web應用防火墻&#xff08;WAF, Web Application Firewall&#xff09;逐漸成為網站和應用的標準防護措施。WAF能夠有效識別和防止如SQL注入、跨站腳本攻擊&#xff08;XSS&#xff09;、惡意流…

小結:路由器和交換機的指令對比

路由器和交換機的指令有一定的相似性&#xff0c;但也有明顯的區別。以下是兩者指令的對比和主要差異&#xff1a; 相似之處 基本操作 兩者都支持類似的基本管理命令&#xff0c;比如&#xff1a; 進入系統視圖&#xff1a;system-view查看當前配置&#xff1a;display current…

Ubuntu中雙擊自動運行shell腳本

方法1: 修改文件雙擊反應 參考: https://blog.csdn.net/miffywm/article/details/103382405 chmod x test.sh鼠標選中待執行文件&#xff0c;在窗口左上角edit菜單中選擇preference設計雙擊執行快捷鍵&#xff0c;如下圖&#xff1a; 方法2: 設置一個應用 參考: https://blo…

從0開始學習搭網站的第一天

前言&#xff0c;以下內容學習自mdn社區&#xff0c;感興趣的朋友可以直接去看原文章web技術 目錄 web機制互聯網是怎么運作的網站服務器是什么什么是URL&#xff1f;什么是web服務器&#xff1f;什么是域名什么是超鏈接什么是網頁DOMgoole瀏覽器開發者工具 web機制 互聯網是怎…

java小灶課詳解:關于char和string的區別和對應的詳細操作

char和string的區別與操作詳解 在編程語言中&#xff0c;char和string是用于處理字符和字符串的兩種重要數據類型。它們在存儲、操作和應用場景上存在顯著差異。本文將從以下幾個方面詳細解析兩者的區別及常見操作。 1. 基本定義與存儲差異 char&#xff1a; 定義&#xff1a;…

黑馬linux筆記(03)在Linux上部署各類軟件 MySQL5.7/8.0 Tomcat(JDK) Nginx RabbitMQ

文章目錄 實戰章節&#xff1a;在Linux上部署各類軟件tar -zxvf各個選項的含義 為什么學習各類軟件在Linux上的部署 一 MySQL數據庫管理系統安裝部署【簡單】MySQL5.7版本在CentOS系統安裝MySQL8.0版本在CentOS系統安裝MySQL5.7版本在Ubuntu&#xff08;WSL環境&#xff09;系統…

[Transformer] The Structure of GPT, Generative Pretrained Transformer

The Structure of Generative Pretrained Transformer Reference: The Transformer architecture of GPT models How GPT Models Work

淺談云計算04 | 云基礎設施機制

探秘云基礎設施機制&#xff1a;云計算的基石 一、云基礎設施 —— 云計算的根基![在這里插入圖片描述](https://i-blog.csdnimg.cn/direct/1fb7ff493d3c4a1a87f539742a4f57a5.png)二、核心機制之網絡&#xff1a;連接云的橋梁&#xff08;一&#xff09;虛擬網絡邊界&#xff…

國內主流的Spring微服務方案指南

構建一個完整的 Spring 微服務方案涉及多個關鍵組件的集成與配置&#xff0c;包括服務注冊與發現、配置管理、API 網關、負載均衡、服務調用、熔斷與限流、消息中間件、分布式追蹤、服務網格、容器編排以及數據庫與緩存等。以下將結合前述內容&#xff0c;詳細介紹一個完整的中…