因为维护项目的需要,得学习一下mobx,之前用过基于redux封装的dav,但是它的model写起来有点费劲,就像vue一样,条条框框,更改状态要不停的的setxxx,getxxx,但是mobx就简化了很多,只需要添加几个修饰器即可
因为react是不支持修饰符的,所以还得下载支持的插件 @babel/plugin-proposal-decorators
customize-cra react-app-rewired @babel/preset-env @babel/core
,在根目录下创建config-overrides.js
,config-overrides.js代码:
const path = require('path')
const { override, addDecoratorsLegacy } = require('customize-cra')
function resolve(dir) {
return path.join(__dirname, dir)
}
const customize = () => (config, env) => {
config.resolve.alias['@'] = resolve('src')
if (env === 'production') {
config.externals = {
'react': 'React',
'react-dom': 'ReactDOM'
}
}
return config
};
module.exports = override(addDecoratorsLegacy(), customize())
更改启动配置
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
创建.babelrc
文件,代码:
{
"presets": [
"@babel/preset-env"
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
]
]
}
globalStore.js
片段:
import {observable,action, makeObservable,makeAutoObservable} from "mobx";
class GlobalStore {
constructor() {
makeObservable(this)
}
@observable loading = true;
@observable count = 100;
@action
setLoading(flag = false) {
console.log('aile')
this.loading = flag;
this.count += 100
}
}
export default GlobalStore;
index.js
片段(将多个modle整合到一起):
import TodoStore from './todoStore';
import GlobalStore from './globalStore';
let todoStore = new TodoStore();
let globalStore = new GlobalStore();
const stores = {
todoStore,
globalStore
}
export default stores;
todoStore.js
片段(没用到):
import {observable, action, computed,makeObservable} from 'mobx';
const INIT_TODO = {
id: 1,
text: 'mobx事例',
completed: false
}
class TodoStore {
constructor() {
makeObservable(this)
}
@observable
todoList = [INIT_TODO];
@computed
get totalTodos() {
return this.todoList.length
}
@action
addTodo(text){
const newTodo = {
id: +new Date(),
text,
completed: false
}
this.todoList = [...this.todoList, newTodo];
}
@action
changeStatus(id) {
this.todoList = this.todoList.map(item => {
return item.id === id
? {...item, completed: !item.completed}
: item
})
}
@action
delTodo(id){
this.todoList = this.todoList.filter(item => item.id !== id)
}
@action
clearTodos() {
this.todoList = [];
}
}
export default TodoStore;
game 下的index.js
片段:
import { useStores } from '../../hooks';
const Game = ()=>{
let store = useStores();
const { globalStore } = store;
return(
<>
<div>game</div>
<div onClick={()=>{globalStore.setLoading(true)}}>增加数据</div>
<span>显示的数据 {globalStore.count}</span>
</>
)
}
export default Game;
home 下的index.js
片段:
import { useObserver } from 'mobx-react-lite';
import { useStores } from '../../hooks';
const Home = ()=>{
let store = useStores();
const { globalStore } = store;
return useObserver(()=>(
<>
<div>首页</div>
<div>我要现实的东西{globalStore.count}</div>
</>
))
}
export default Home;
index.js
代码:
import { Routes, Route, Link, BrowserRouter as Router } from 'react-router-dom';
import { Observer, Provider, useLocalStore, useObserver } from 'mobx-react'
import { useStores } from '../hooks';
import stores from '@/store/index.js'
import Home from '../pages/home'
import Game from '../pages/game'
import './index.css'
const Layout = () => {
const localStore = useLocalStore(() => stores);
const { globalStore } = localStore
return useObserver(() =>(
<Router>
<div>
<Link to={`/`}>首页</Link>
<Link to={`/game`}>游戏</Link>
<span>{localStore.globalStore.count}</span>
<button onClick={()=>{globalStore.setLoading(true)}}>添加</button>
</div>
<Routes>
<Route path='/' element={<Home />} />
<Route path='/game' element={<Game />} />
</Routes>
</Router>
))
}
export default Layout;
index.js
代码:
import React from 'react';
import stores from '../store';
export const StoresContext = React.createContext({
...stores
})
index.js
代码:
import React from 'react'
import { StoresContext } from '../contexts';
export const useStores = () => React.useContext(StoresContext)
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import Layout from './router/index'
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Layout />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();