目录
1.运行项目
2. 项目结构
①项目顶部导航栏
②项目左侧导航栏
③主页面-路由切换区
本项目使用的是 react+ts+scss 技术栈。
1.运行项目
在当前页面顶部下载本项目,解压后使用编辑器打开,然后再终端输入命令:
npm i
下载依赖后,运行项目:
npm run start
此时项目运行起来了,可以再浏览器看到运行效果:
2. 项目结构
在做自己的项目时,对于这个项目目录我们只需要更改以下几个文件:
src目录下的文件和App.tsx,可以根据自己项目需要进行更改。
①项目顶部导航栏
header.tsx:
import logo from '../../assets/images/logo.svg';
import './header.scss';
function Header() {
return (
<div className="headerAll">
<header className="headerBox">
<img src={logo} alt="logo" className='headerImg' />
<div className="headerText">后台管理系统</div>
<div className="circle">zh</div>
</header>
<header className="headerBoxPlaceholder">
</header>
</div>
);
}
export default Header;
header.scss:
.headerBox {
width: 100vw;
height: 56px;
background-color: #FFF;
position: fixed;
top: 0;
left: 0;
z-index: 9;
min-width: 1140px;
overflow: auto;
.headerImg {
width: 30px;
height: 30px;
position: absolute;
top: 13px;
left: 17px;
}
.headerText {
font-size: 20px;
position: absolute;
top: 14px;
left: 57px;
font-weight: bold;
}
.navText {
font-size: 16px;
position: absolute;
top: 16px;
left: 218px;
}
.circle {
width: 28px;
height: 28px;
line-height: 28px;
border-radius: 50%;
background-color: #19edcd;
position: absolute;
top: 14px;
right: 14px;
font-size: 12px;
color: #FFF;
text-align: center;
}
}
.headerBoxPlaceholder {
width: 100vw;
height: 56px;
box-shadow: 0px 4px 10px 0px rgba(78, 89, 105, 0.06);
}
②项目左侧导航栏
leftNavigation.tsx:
使用左侧导航图标使用svg,方便切换状态时换色,以及后期更改主题色。
import { ReactComponent as IconEducationGroup } from '../../assets/images/icon-education-group.svg';
import { ReactComponent as IconEduGroup } from '../../assets/images/icon-edu-group.svg';
import { ReactComponent as IconSet } from '../../assets/images/icon-set.svg';
import Arrow from "../../assets/images/icon-arrow.png";
import './leftNavigation.scss';
import { useState } from 'react';
function LeftNavigation() {
// 左侧导航,一级按钮
let navText = ['企业信息', '组织管理', '系统设置'];
// 二级导航按钮,比如企业信息没有子级则二级导航为空数组
let navTextChild = [[], ['组织架构', '部门设置'], ["日志设置", '通知设置']];
// 当前选中的是哪个按钮,0是一级按钮,-1代表它没有子级选中的就是它本身
const [currentBtn, setCurrentBtn] = useState([0, -1]);
// 如果存在子层级,子层级展开还是合并,0合并,1展开
const [childShow, setChildShow] = useState([1, 1, 1, 1]);
/**
* 判断按钮背景颜色
* @param index 索引
* @param flag 标志
* @param indexChild 二级索引
* @returns 返回className
*/
function changeBGColor(index: number, flag: string, indexChild?: number): string {
if (flag === 'one') {
if (navTextChild[index].length === 0) {
if (currentBtn[0] === index && navTextChild[index].length === 0) return 'first-order-tag bg-color'
}
} else {
if (navTextChild[index].length !== 0 && currentBtn[0] === index && currentBtn[1] === indexChild) return 'first-order-tag bg-color'
}
return 'first-order-tag';
}
/**
* 点击导航按钮进行页面切换
* @param indexOne 一级索引
* @param indexTwo 二级索引
*/
function changeNavClick(indexOne: number, indexTwo?: number): void {
if (navTextChild[indexOne].length === 0) { setCurrentBtn([indexOne, -1]) }
if (indexTwo !== undefined && navTextChild[indexOne].length !== 0) {
setCurrentBtn([indexOne, indexTwo])
}
if (indexTwo === undefined && navTextChild[indexOne].length !== 0) {
updateItem(indexOne, childShow[indexOne] === 1 ? 0 : 1)
}
}
/**
* 只更新数组中的一个数值,数组[1]的值
* @param indexFlag 一级索引
* @param newValue 新的数值
*/
function updateItem(indexFlag: number, newValue: number) {
setChildShow(prevItems =>
prevItems.map((item, index) => {
if (index === indexFlag) {
return newValue;
}
return item;
})
);
}
return (
<div className="leftNavigationAll">
<div className="leftNavigationBox">
{navText.map((item, index) => (
<div key={index}>
{/* 第一层级 */}
<div key={index} className={changeBGColor(index, 'one')} onClick={() => changeNavClick(index)}>
<div className={currentBtn[0] === index ? 'navTextStyle-selected' : 'navTextStyle'}> {item}</div>
{index === 0 && <IconEducationGroup className="icon-svg" stroke={currentBtn[0] === index ? '#00B498' : '#505553'} />}
{index === 1 && <IconEduGroup className="icon-svg" stroke={currentBtn[0] === index ? '#00B498' : '#505553'} />}
{index === 2 && <IconSet className="icon-svg" stroke={currentBtn[0] === index ? '#00B498' : '#505553'} fill={currentBtn[0] === index ? '#00B498' : '#505553'} />}
{navTextChild[index].length !== 0 && <img alt="箭头" src={Arrow} className={childShow[index] === 1 ? 'arrow' : 'arrowHidden'}></img>}
</div>
{/* 第二层级 */}
<div className={childShow[index] === 1 ? 'showDiv' : 'hiddenDiv'}>
{navTextChild[index].length !== 0 && navTextChild[index].map((itemChild, indexChild) => (
<div key={indexChild} className={changeBGColor(index, 'two', indexChild)} onClick={() => changeNavClick(index, indexChild)}>
<div className={(currentBtn[1] === indexChild && currentBtn[0] === index) ? 'navTextStyle-selected' : 'navTextStyle'}> {itemChild}</div>
</div>
))}
</div>
</div>
))}
</div>
</div>
);
}
export default LeftNavigation;
leftNavigation.scss:
.bg-color {
background-color: #E8FAF8;
}
.showDiv {
display: block;
}
.hiddenDiv {
display: none;
}
.leftNavigationBox {
z-index: 8;
width: 200px;
height: 100vh;
min-height: 400px;
background-color: #FFF;
position: fixed;
top: 0;
left: 0;
padding-top: 72px;
padding-left: 8px;
padding-right: 8px;
box-sizing: border-box;
.first-order-tag {
width: 184px;
height: 40px;
// background-color: #E8FAF8;
margin-bottom: 4px;
border-radius: 6px;
position: relative;
cursor: pointer;
&:hover {
background-color: #F2F5F4;
}
.arrow {
width: 12px;
height: 12px;
position: absolute;
right: 16px;
top: 14px;
transform: rotateZ(180deg);
}
.arrowHidden {
width: 12px;
height: 12px;
position: absolute;
right: 16px;
top: 14px;
// transform: rotateZ(180deg);
}
.icon-svg {
width: 18px;
height: 18px;
position: absolute;
left: 12px;
top: 11px;
}
.navTextStyle {
font-size: 14px;
color: #505553;
position: absolute;
left: 42px;
top: 9px;
}
.navTextStyle-selected {
font-size: 14px;
color: #00B498;
position: absolute;
left: 42px;
top: 9px;
}
}
}
③主页面-路由切换区
App.tsx:
所有路由写在这里,然后再左侧导航栏进行切换。
import './App.scss';
import Header from './pages/navigation/header';
import LeftNavigation from './pages/navigation/leftNavigation';
import Home from './pages/home';
import { Route, Routes } from 'react-router-dom'
function App() {
return (
<div className="App">
<Header />
<LeftNavigation />
{/* 2. 使用路由组件,渲染路由,并且传入路由配置 */}
<Routes>
{/* comopnent替换为 element */}
<Route path='/' element={<Home />}></Route>
</Routes>
</div>
);
}
export default App;
home / index.tsx:
import './index.scss';
function Home() {
return (
<div className='homeBox'>
<div className='homeBoxText'>应用主页</div>
</div>
);
}
export default Home;
以上就是项目的主要内容,可以将此项目当作基础框架进行二次开发。