- 文件层级
my-react-app
- src
- components
- timerUI.jsx
- withTimerLogic.jsx
- pages
- home.jsx
- login.jsx
- page1.jsx
- page2.jsx
- stores
- authStore.js
- app.jsx
- index.js
- components
- public
- index.html
- id=“root”
- index.html
注释:
- src:源代码
- components:react组件,被多次调用,页面的一部分
- pages:react页面,被app.js调用,能单独成页面
- stores:全局状态仓库
- app.jsx:react根组件
- index.js:react应用的入口文件,将react组件挂载到html文件的根节点上,启动了整个react应用
- public:静态文件
- index.html:web应用的html入口文件,不是react组件
- id=“root”:react应用的根节点、起点,react组件首次渲染到html文件的位置,承载着整个react应用的内容
- react类组件使用mobx管理登录状态
- index.html(包含了根节点)
<!--idea中输入html5回车,自动生成模板-->
<!doctype html>
<html>
<head>
<meta>
<title>my-react-app</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
- index.js(将根组件挂载到根节点、分发全局登录状态,提供路由功能)
import React from "react"
import ReactDOM from "react-dom"
import {Provider} from "mobx-react"
import authStore from "./stores/authStore"
import {BrowserRouter as Router} from "react-router-dom"
import App from "./app"
ReactDOM.render(
<Provider authStore={authStore}>
<Router>
<App/>
</Router>
</Provider>
,
document.getElementById("root")
)
- authStore.js(管理全局登录状态)
import {observable,action} from "mobx"
class AuthStore{
//不需要extends Component,因为不是react组件,不负责渲染UI
//不能直接export default,因为需要导出的是一个实例,不是一个类,用单例模式来保证全局登录状态一致
//变量不需要存储在state中,因为不需要刷新UI了
@observable isAuth=false
@observable userName=""
@observable token=""
constructor(){
//不属于组件,没有生命周期
//希望在实例化时能够从LS中读取用户token,这样有效期内不需要每天重新登录
this.getUserInfo()
}
@action
setUserInfo(newUserInfo){
//存储到状态仓库,全局共享,但关掉浏览器会清空
this.isAuth=true
this.userName=newUserInfo.userName
this.token=newUserInfo.token
//存储到浏览器,关掉浏览器不会清空,持久化
localStorage.setItem("userInfo",JSON.stringify(newUserInfo))
}
@action
clearUserInfo(){
this.isAuth=false
this.userName=""
this.token=""
localStorage.removeItem("userInfo")
}
@action
getUserInfo(){
const userInfoLS=localStorage.getItem("userInfo")
if(userInfoLS){
const userInfo=JSON.parse(userInfoLS)
this.setUserInfo(userInfo)
}
}
}
const authStore=new AuthStore()
export default authStore
- app.jsx(根组件、配置路由规则)
import React,{Component} from "react"
import {Layout,Menu,Button,Image} from "antd"
import {Link,Switch,Redirect,Route} from "react-router-dom"
import {inject,observer} from "mobx-react"
import Home from "./pages/home"
import Login from "./pages/login"
import Page1 from "./pages/page1"
import Page2 from "./pages/page2"
const {Header,Content}=Layout
@inject("authStore")
@observer
export default class App extends Component{
render(){
return(
<Layout>
<Header>
<Image src={"minio地址"} alt="项目logo"/>
{this.props.authStore.isAuth&&
(<>
<Menu>
<Menu.Item key="home">
<Link to="/">首页</Link>
</Menu.Item>
<Menu.Item key="page1">
<Link to="/page1">页面1</Link>
</Menu.Item>
<Menu.Item key="page2">
<Link to="/page2">页面2</Link>
</Menu.Item>
</Menu>
<Button
onClick={this.props.authStore.clearUserInfo}
>登出</Button>
</>)}
</Header>
<Content>
<Switch>
{!this.props.authStore.isAuth&&<Redirect to="/login"/>}
<Route path="/" component={Home} exact/>
<Route path="/login" component={Login}/>
<Route path="/page1" component={Page1}/>
<Route path="/page2" component={Page2}/>
</Switch>
</Content>
</Layout>
)
}
}
- login.jsx(登录组件)
import React,{Component} from "react"
import {Layout,Form,Input,Button,message} from "antd"
import axios from "axios"
import {inject,observer} from "mobx-react"
const {Content}=Layout
@inject("authStore")
@observer
export default class Login extends Component{
handleLogin=values=>{
axios.post("接口地址",{
username:values.username,
password:values.password})
.then(response=>{
if(response.data.token){
this.props.authStore.setUserInfo(response.data)
message.success("登录成功")
this.props.history.push("/")
}else{
message.error("账号密码不存在")
}
})
.catch(error=>{
message.error("请求失败")
})
}
render(){
return(
<Content>
<Form onFinish={this.handleLogin}>
<Form.Item name="username" label="用户名">
<Input/>
</Form.Item>
<Form.Item name="password" label="密码">
<Input.Password/>
</Form.Item>
<Form.Item>
<Button htmlType="submit">登录</Button>
</Form.Item>
</Form>
</Content>
)
}
}
- home.jsx、page.jsx(其他组件)
import React,{Component} from "react"
import {observer} from "mobx-react"
import {Layout} from "antd"
const {Content}=Layout
@observer
export default Home extends Component{
render(){
return(
<Content>
这是首页
</Content>
)
}
}
- react函数组件使用mobx管理登录状态
- index.html
<!doctype html>
<html>
<head>
<meta>
<title>my-react-app</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
- index.js
import React from "react"
import ReactDOM from "react-dom"
import {Provider} from "mobx-react"
import authStore from "./stores/authStore"
import {BrowserRouter as Router} from "react-router-dom"
import App from "./app"
ReactDOM.render(
<Provider authStore={authStore}>
<Router>
<App/>
</Router>
</Provider>
,document.getElementById("root"))
- authStore.js
import {observable,action} from "mobx"
class AuthStore{
@observable isAuth=false
@observable username=""
@observable token=""
constructor(){
this.getUserInfo()
}
@action
getUserInfo(){
const userInfoLS=localStorage.getItem("userInfo")
//localStorage是web api的一部分,不需要导入
if(userInfoLS){
const userInfo=JSON.parse(userInfoLS)
//JSON是js语言的一部分,parse是js的内置方法,不需要导入
this.setUserInfo(userInfo)
}
}
@action
setUserInfo(newUserInfo){
this.isAuth=true
this.username=newUserInfo.username
this.token=newUserInfo.token
localStorage.setItem("userInfo",JSON.stringify(newUserInfo))
}
@action
clearUserInfo(){
this.isAuth=false
this.username=""
this.token=""
localStorage.removeItem("userInfo")
}
const authStore=new AuthStore()
export default authStore
}
- app.jsx
import React from "react"
import {inject,observer} from "mobx-react"
import {Layout,Image,Menu,Button} from "antd"
import {Link,Redirect,Switch,Route} from "react-router-dom"
import Home from "./pages/home"
import Login from "./pages/login"
import Page1 from "./pages/page1"
import Page2 from "./pages/page2"
const {Header,Content}=Layout
export default inject("authStore")(observer(({authStore})=>{
return(
<Layout>
<Header>
<Image src="minio地址" alt="项目logo"/>
{authStore.isAuth&&
(<>
<Menu>
<Menu.Item key="home">
<Link to="/">首页</Link>
</Menu.Item>
<Menu.Item key="page1">
<Link to="/page1">页面1</Link>
</Menu.Item>
<Menu.Item key="page2">
<Link to="/page2">页面2</Link>
</Menu.Item>
</Menu>
<Button onClick={authStore.clearUserInfo}>登出</Button>
</>)}
</Header>
<Content>
<Switch>
{!authStore.isAuth&&<Redirect to="/login" />}
<Route path="/" component={Home} exact/>
<Route path="/login" component={Login}/>
<Route path="/page1" component={Page1}/>
<Route path="/page2" component={Page2}/>
</Switch>
</Content>
</Layout>
)
}))
- login.jsx
import React from "react"
import axios from "axios"
import {inject,observer} from "mobx-react"
import {Layout,Form,Input,Button,message} from "antd"
const {Content}=Layout
export default inject("authStore")(observer(({authStore})=>{
handleLogin=(values)=>{
axios.post("接口地址",{
username:values.username,
password:values.password
}).then(response=>{
if(response.data.token){
authStore.setUserInfo(response.data)
message.success("登录成功")
props.history.push("/")
}else{
message.error("登录失败")
}
}).catch(error=>{
message.error("请求失败")
})
}
return(
<Content>
<Form onFinish={handleLogin}>
<Form.Item name="username" label="用户名">
<Input/>
</Form.Item>
<Form.Item name="password" label="密码">
<Input.Password/>
</Form.Item>
<Form.Item>
<Button htmlType="submit">登录</Button>
</Form.Item>
</Form>
</Content>
)
}))
- home.jsx
import React from "react"
import {observer} from "mobx-react-lite"
import {Layout} from "antd"
const {Content}=Layout
export default observer(()=>{
return(
<Content>
这是首页
</Content>
)
})