目录
实现admin组件在home组件中展示路由切换只在home页面完成
一、核心概念
中文官网:开始 – React
二、状态管理
Redux中文官网: 自述 · Redux
实例一、简易的按钮增加和减少
changeState.js
let state = {
count: 0,
};
const changeState = (action) => {
action = action || { type: "" };
switch (action.type) {
case "increment":
return {
...state,
count: state.count++,
};
case "decrement":
return {
...state,
count: state.count++,
};
default:
return state
}
};
export { changeState };
store1.js
import { changeState } from "./changeState";
let state = {}
const createStore = () => {
// 获取状态
const getState = () => {
return state;
};
//观察者模式
const listeners = [];
const subscribe = (listener) => listeners.push(listener);
const dispatch = (action) => {
state = changeState()
changeState(action);
//publish
listeners.forEach((listener) => listener());
render();
};
return {
dispatch,
getState,
subscribe,
};
};
const store = createStore();
const render = () => {
document.getElementById("count").innerHTML = store.getState().count
};
store.subscribe(render);
export default store;
App.jsx
import React from "react";
import store from "./store1";
class App extends React.Component{
render(){
return(
<div>
<button onClick={store.dispatch.bind(this,{type:'decrement'})}>-</button>
<span id="count"></span>
<button onClick={store.dispatch.bind(this,{type:'increment'})}>+</button>
</div>
)
}
componentDidMount(){
store.dispatch()
}
}
export default App
三、路由管理
入口文件index.js
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<App></App>
);
App.jsx
import {BrowserRouter,Route,Routes} from 'react-router-dom'
import React from 'react'
import Home from './views/home'
import Login from './views/login'
class App extends React.Component{
render(){
return(
<BrowserRouter>
<Routes>
<Route path='/' element={<Login/>}></Route>
<Route path='/home/*' element={<Home/>}></Route>
</Routes>
</BrowserRouter>
)
}
}
export default App
login.jsx
import React from "react";
class Login extends React.Component{
render(){
return(
<div>
Login页面
</div>
)
}
}
export default Login
子路由实现
实现admin组件在home组件中展示路由切换只在home页面完成
home.jsx
import React from "react";
import { Route, Link, Routes } from "react-router-dom";
import Admin from "./admin/admininfo";
class Home extends React.Component {
render() {
return (
<div>
Home页面
<li>
<Link to="/home/admin">admininfo</Link>
</li>
<div>
<Routes>
<Route path="/admin" element={<Admin />}></Route>
</Routes>
</div>
</div>
);
}
}
export default Home;
1.登陆成功页面跳转路由实现
import { Navigate } from "react-router";
impost axios from 'axios'
class Login extends React.Component {
state = {
loginflag: false,
};
login = ()=>{
axios.post(url,params).then(res=>{
if(res){
this.setState({
longiflag:true
})
}
})}
render() {
//当登录成功时表达式被执行页面跳转
if(this.state.loginflag){
return <Navigate to="/home" />
}
return (
<div>
<button onClick={this.login}>登录</button>
</div>
)
}
四、实战React+antd
react-yeb
问题一、登录成功页面跳转
解决:定义一个state:loginflag:false
用 Navigate组件在render函数里
if(this.state.loginflag){
return <Navigate to="/home" />
}请求成功把loginflag改为true
import React from "react";
import { Button, Input } from "antd";
import "../css/login.css";
import { Navigate } from "react-router";
import { postRequset } from "../store/api";
class Login extends React.Component {
state = {
captchaimage: "/api/captcha?time=" + new Date(),
username: "",
password: "",
code: "",
loginflag: false,
};
componentDidMount() {}
login = () => {
let data = {
username: this.state.username,
password: this.state.password,
code: this.state.code,
loginflag:false
};
postRequset("/api/login", data).then((res) => {
if (res) {
const tokenStr =res.obj.tokenHead+res.obj.token
window.sessionStorage.setItem('tokenStr',tokenStr)
this.setState({
loginflag:true
})
}
});
};
urlUpdate = () => {
this.setState({
captchaimage: "/api/captcha?time=" + new Date(),
});
};
render() {
if(this.state.loginflag){
return <Navigate to="/home" />
}
return (
<div id="login">
<div className="loginarea">
<div
style={{
position: "relative",
top: "10%",
fontSize: "30px",
letterSpacing: "15px",
left: "29%",
fontWeight: "bolder",
color: "#505458",
}}
>
欢迎登陆
</div>
<div style={{ position: "relative", top: "20%", left: "10%" }}>
<span>账号:</span>
<Input
size="large"
style={{ width: "300px", marginLeft: "10px" }}
onChange={(e) => this.setState({ username: e.target.value })}
></Input>
</div>
<div style={{ position: "relative", top: "22%", left: "10%" }}>
<span>密码:</span>
<Input
size="large"
onChange={(e) => this.setState({ password: e.target.value })}
style={{ width: "300px", marginLeft: "10px" }}
></Input>
</div>
<div style={{ position: "relative", top: "26%", left: "10%" }}>
<span style={{ position: "relative", right: "3%", bottom: "17px" }}>
验证码:
</span>
<Input
size="large"
onChange={(e) => this.setState({ code: e.target.value })}
placeholder="请输入验证码"
style={{
width: "120px",
position: "relative",
bottom: "17px",
height: "37px",
borderRadius: "0",
marginLeft: "-5px",
marginRight: "2px",
}}
></Input>
<img
onClick={this.urlUpdate}
src={this.state.captchaimage}
width={95}
style={{
position: "relative",
marginLeft: "0.5px",
bottom: "5px",
}}
></img>
</div>
<div style={{ position: "relative", top: "26%", left: "10%" }}>
<Button
size="large"
type="primary"
onClick={this.login}
style={{ width: 100, margin: "10px", left: "8%" }}
>
登录
</Button>
<Button
size="large"
style={{ width: 100, margin: "10px", left: "15%" }}
>
退出
</Button>
</div>
</div>
</div>
);
}
}
export default Login;
问题二、点击子菜单路由跳转
解决:使用链式链接导航
import React from "react";
import { getRequest } from "../store/api";
import { Menu } from "antd";
import "../../node_modules/font-awesome/css/font-awesome.min.css";
import { Routes, Route, Navigate, Link } from "react-router-dom";
import EmpBasic from "./emp/EmpBasic";
import PerEc from "./per/PerEC";
import PerEmp from "./per/PerEmp";
import PerMv from "./per/PerMv";
import PerSalary from "./per/PerSalary";
import PerTrain from "./per/PerTrain";
import SalMonth from "./sal/SalMonth";
import SalSearch from "./sal/SalSearch";
import SalSob from "./sal/SalSob";
import SalSobCfg from "./sal/SalSobCfg";
import SalTable from "./sal/SalTable";
import StaAll from "./sta/StaAll";
import StaPers from "./sta/StaPers";
import StaRecord from "./sta/StaRecord";
import StaScore from "./sta/StaScore";
import SysAdmin from "./sys/SysAdmin";
import SysBasic from "./sys/SysBasic";
import SysCfg from "./sys/SysCfg";
import SysData from "./sys/SysData";
import SysInit from "./sys/SysInit";
import SysLog from "./sys/SysLog";
function getItem(label, key, icon, children, type) {
return {
key,
icon,
children,
label,
type,
};
}
class Home extends React.Component {
state = {
routes: "/home/per/emp",
item: [],
keys: [],
openKeys: ["2"],
flag: false,
};
//实现只保留一个菜单
onOpenChange = (key1) => {
const latestOpenKey = key1.find(
(key) => this.state.openKeys.indexOf(key) === -1
);
if (this.state.keys.indexOf(latestOpenKey) === -1) {
this.setState({
openKeys: [key1],
});
} else {
this.setState({ openKeys: latestOpenKey ? [latestOpenKey] : [] });
}
};
componentDidMount() {
getRequest("/api/system/cfg/menu").then((res) => {
let list = [];
let opkeys = [];
if (res) {
res.forEach((item) => {
opkeys.push(item.id + "");
//子菜单列表 使用Link组件进行跳转
let childrenlist = [];
if (item.children) {
item.children.forEach((children) => {
childrenlist.push(
getItem(
children.name,
"/home" + children.path,
<Link to={"/home" + children.path}></Link>,
null
)
);
});
}
list.push(
getItem(
item.name,
item.id,
<i className={item.iconCls} style={{ color: "#1accff" }}></i>,
childrenlist
)
);
});
this.setState({
item: list,
keys: opkeys,
});
}
});
}
render() {
return (
<div>
<div
style={{ width: "100%", height: "88px", backgroundColor: "#5fa5f3" }}
>
<div style={{width:'20%',lineHeight:'80px',color:'white',fontWeight:'lighter',fontSize:'70px',fontFamily:"楷体",letterSpacing:'10px'}}>云e办</div>
</div>
<Menu
openKeys={this.state.openKeys}
onOpenChange={this.onOpenChange}
mode="inline"
multiple={false}
style={{ width: "12%" }}
items={this.state.item}
></Menu>
<div
style={{
width: "88%",
height: "87.6%",
position: "absolute",
left: "12%",
bottom: "0",
}}
>
<Routes>
<Route path="/emp/basic" element={<EmpBasic />}></Route>
<Route path="/per/emp" element={<PerEmp />}></Route>
<Route path="/per/ec" element={<PerEc />}></Route>
<Route path="/per/train" element={<PerTrain />}></Route>
<Route path="/per/salary" element={<PerSalary />}></Route>
<Route path="/per/mv" element={<PerMv />}></Route>
<Route path="/sal/sob" element={<SalSob />}></Route>
<Route path="/sal/sobcfg" element={<SalSobCfg />}></Route>
<Route path="/sal/table" element={<SalTable />}></Route>
<Route path="/sal/month" element={<SalMonth />}></Route>
<Route path="/sal/search" element={<SalSearch />}></Route>
<Route path="/sta/all" element={<StaAll />}></Route>
<Route path="/sta/score" element={<StaScore />}></Route>
<Route path="/sta/pers" element={<StaPers />}></Route>
<Route path="/sta/record" element={<StaRecord />}></Route>
<Route path="/sys/basic" element={<SysBasic />}></Route>
<Route path="/sys/cfg" element={<SysCfg />}></Route>
<Route path="/sys/log" element={<SysLog />}></Route>
<Route path="/sys/admin" element={<SysAdmin />}></Route>
<Route path="/sys/data" element={<SysData />}></Route>
<Route path="/sys/init" element={<SysInit />}></Route>
</Routes>
</div>
</div>
);
}
}
export default Home;