react用mobx进行全局状态管理

  1. 文件层级

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
  • public
    • index.html
      • id=“root”

注释:

  • 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应用的内容
  1. 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>
  )
 }
}
  1. 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>
 )
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值