redux和mobx入门使用

项目涉及技术

公共插件

  • create-react-app
  • react-dom
  • react-router
  • react-router-dom
  • react-hook
  • redux
  • react-redux

大概实现功能

  • 组件调用
  • 路由跳转
  • 接口调用
  • 状态管理

代码示例说明

redux 和 mobx 的层级结构如下

redux-mobx

├── README.md

├── mobx-demo

│ ├── README.md

│ ├── config-overrides.js

│ ├── package-lock.json

│ ├── package.json

│ ├── public

│ │ ├── favicon.ico

│ │ ├── index.html

│ │ ├── logo192.png

│ │ ├── logo512.png

│ │ ├── manifest.json

│ │ └── robots.txt

│ └── src

│ ├── App.css

│ ├── App.js

│ ├── App.test.js

│ ├── compments

│ │ ├── compnentA.js

│ │ └── compnentB.js

│ ├── index.css

│ ├── index.js

│ ├── logo.svg

│ ├── pages

│ │ ├── bar.js

│ │ └── foo.js

│ ├── reportWebVitals.js

│ ├── setupTests.js

│ └── store

│ ├── index.js

│ └── storeone.js

├── package-lock.json

└── redux-demo

├── README.md

├── package-lock.json

├── package.json

├── public

│ ├── favicon.ico

│ ├── index.html

│ ├── logo192.png

│ ├── logo512.png

│ ├── manifest.json

│ └── robots.txt

└── src

├── App.css

├── App.js

├── App.test.js

├── compments

│ ├── compnentA.js

│ └── compnentB.js

├── index.css

├── index.js

├── logo.svg

├── pages

│ ├── bar.js

│ └── foo.js

├── reportWebVitals.js

├── setupTests.js

└── store

├── index.js

└── reducer.js

项目基础脚手架使用 create-react-app 生成,新建三个文件夹,组件集components, 页面集 pages, 以及状态管理集 store。

1.App.js

    import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import reportWebVitals from './reportWebVitals';
import App from './App';
// 添加代码如下
import Foo from './pages/foo';
import Bar from './pages/bar';
import {HashRouter, Route, Switch } from 'react-router-dom'
import {Provider} from 'react-redux';
import store from './store/index'
ReactDOM.render(
<Provider store = {store}>
<React.StrictMode>
<h1>redux-demo</h1>
<HashRouter>
<Switch>
<Route exact path="/foo" component={Foo}/>
<Route exact path="/bar" component={Bar}/>
<Route exact path="/" component={App} />
</Switch>
</HashRouter>
</React.StrictMode>
</Provider>,
document.getElementById('root')
);
reportWebVitals();

引入页面Foo, Bar,路由 react-router-dom插件,以及状态管理 react-redux。状态统一管理 store/index.js,这里统一管理store。

通过Provider 传入 store,包裹所有组件,这样组件内部能拿到store数据。

注意

这里的 Switch组件,当匹配到一个路由的时候,就不用往下匹配,这个也是项目优化的一个部分。

2.store 处理

store

├── index.js

└── reducer.js

index.js

我这里演示的是一个reducer,如果是多个reducer 可以用 combineReducers 进行合并

    import { createStore } from 'redux';
import reducer from './reducer';
export default createStore(reducer)

定义简单的action

reducer.js

    const defaultState = {
count: 1,
pageName: "default page"
} const Store = (state = defaultState, action) => {
switch(action.type) {
case 'COUNT_ADD':
state.count += action.value;
break;
case 'COUNT_SUB':
state.count -= action.value;
break;
case 'COUNT_MUTIL':
state.count *= action.value;
break;
default:
state.count = defaultState.count;
} return {
...state
}
} export default Store

3.页面路由 bar.js

    import React from 'react';
import { connect } from 'react-redux'; // 组件B中获取count的值
function Bar(props) {
const { count, pageName} = props
return <div>
<h2>Bar</h2>
<p>count: {count}</p>
<p>pageName: {pageName}</p>
</div>
} const BarPage = connect(state => (
state
))(Bar) export default BarPage;

使用redux中 connect 将组件和store链接起来。connect 一共四个参数,可以看这个文章connect,这个组件里 我们只用里第一个参数,将store 中的值 传递给组件,这样 Bar 函数组件props里面就有我们传进来的数据。

4.页面路由 foo.js

    import React, {useState, useEffect} from 'react';
import { connect } from 'react-redux'
// 组件B中获取count的值
// http://localhost:4000/get/alluser 接口地址
const Foo = (props) => {
const { count } = props
const [ allData, setAllData ] = useState([]);
useEffect(()=>{
fetch("http://localhost:4000/get/alluser").then(res => {
res.json().then(data => {
setAllData(data.users)
})
})
},[]) return <div>
<h2>Foo</h2>
<p>count: {count}</p>
<ul>
{allData.map((item,index)=>{
return <li key={index}>
<p>{item.name}</p>
<img src={item.avatar_url} width="180"/>
</li>
})}
</ul>
</div>
} const FooPage = connect(state => (
{
count: state.count
}
))(Foo) export default FooPage

注意

  1. 这里的connect 第一个参数,跟上面的例子差不多,返回的是state 里面一个具体的值,这样可以控制页面组件里的具体数据。
  2. HOOK 组件 使用useEffect 调用接口,获取数据,渲染页面。对于HOOK的使用 不是我们这节的重点,具体学习可以查看react-hook

5.组件 commentA.js

注意,重点

    import React from 'react';
import { connect } from 'react-redux'
import { Link } from 'react-router-dom' const CompnentA = (props) => {
// const [count, SetCount] = useState(props.count)
const addCount = () => {
const { changeCount } = props;
changeCount({
type: "COUNT_ADD",
value: 3,
})
}
const subCount = () => {
const { changeCount } = props;
changeCount({
type: "COUNT_SUB",
value: 1,
})
}
const mutilCountfun = () => {
const {mutilCount} = props;
mutilCount({
type: 'COUNT_MUTIL',
value: 10
})
}
return <div>
<h2>组件A</h2>
<p><button onClick={addCount}>count +3</button></p>
<p><button onClick={subCount}>count -1</button></p>
<p><button onClick={mutilCountfun}>count * 10</button></p>
<ul>
<li><Link to="/foo">Foo 页面</Link></li>
<li><Link to="/bar">Bar 页面</Link></li>
<li><Link to="/">APP 主页面</Link></li>
</ul>
</div>
} const Compnent = connect(null, dispatch => ({
changeCount: ({type, value}) => dispatch({
type,
value,
}),
mutilCount: ({type, value}) => dispatch({
type,
value
})
}))(CompnentA) export default Compnent

connect 第一个参数,因为不需要,我们没有传store进组件,第二个函数参数mapDispatchToProps,我们传递了一些action方法进去,这些方法会绑定到组件当中。

我们知道我们不能直接修改store 里面的数据,我们需要通过派发器(dispatch)派发一个动作(action),这也是唯一修改state的方法,

这个action方法会触发我们的reducer方法 ,根据对应的action,返回对应的state。

6.组件 comnentB.js

通过上面 componentA的操作,我们已经修改了state 值,在componentB 中就体现出来了,代码如下

    import React  from 'react';
import { connect } from 'react-redux' // 组件B中获取count的值
function CompnentB(props) {
const { count } = props
return <div>
<h2>组件B</h2>
<p>count: {count}</p>
</div>
} const CompnentBB = connect(state => (
{
count: state.count
}
))(CompnentB) export default CompnentBB

整体效果,图片如下

以上是redux 部分的demo,我们继续使用mobx,整个项目复制一遍,我们修改下数据管理部分和页面使用状态数据部分,其他层级不变,开始的项目结构可以看出。

mobx-demo

1. index.js

    import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import reportWebVitals from './reportWebVitals'; import App from './App';
import Foo from './pages/foo';
import Bar from './pages/bar';
import { configure } from "mobx";
import { Provider } from "mobx-react";
import store from './store/index'
import {HashRouter, Route, Switch } from 'react-router-dom'
configure({ enforceActions: "observed" });
ReactDOM.render(
<Provider store = {store}>
<React.StrictMode>
<h1>mobx-demo</h1>
<HashRouter>
<Switch>
<Route exact path="/foo" component={Foo}/>
<Route exact path="/bar" component={Bar}/>
<Route exact path="/" component={App} />
</Switch>
</HashRouter>
</React.StrictMode>
</Provider>,
document.getElementById('root')
); reportWebVitals();

这里主要是将redux 的Provider 替换成 mobx的Provider

2. store/index

store

├── index.js

└── storeone.js

  1. index.js

        import StoreOne from "./storeone";
    class Store {
    constructor() {
    this.storeOne = StoreOne;
    }
    }
    export default new Store();
  2. storeone.js

        import { observable, action, makeObservable } from 'mobx';
    class appStore {
    constructor() {
    // 添加makeObservable mobx6.0 状态数据已经修改,但是页面没有更新,需要通过这个方法来强制更新数据
    makeObservable(this)
    }
    // state
    @observable count = 1;
    @observable pageName = "default pageName"; // getter
    get skinWindow() {
    return {
    };
    } // action
    @action
    addCount(payload) {
    this.count += payload;
    }
    @action
    subCount(payload) {
    this.count -= payload;
    } @action
    mutilCountfun(payload) {
    this.count *= payload;
    }
    }
    const as = new appStore();
    export default as

3.componentA 组件使用

    import React from 'react';
import { Link } from 'react-router-dom'
import { observer, inject } from 'mobx-react'; const CompnentA = (props) => {
const {storeOne} = props.store
const addCount = () => {
storeOne.addCount(3)
}
const subCount = () => {
storeOne.subCount(1)
}
const mutilCountfun = () => {
storeOne.mutilCountfun(10)
}
return <div>
<h2>组件A</h2>
<p><button onClick={addCount}>count +3</button></p>
<p><button onClick={subCount}>count -1</button></p>
<p><button onClick={mutilCountfun}>count * 10</button></p>
<ul>
<li><Link to="/foo">Foo 页面</Link></li>
<li><Link to="/bar">Bar 页面</Link></li>
<li><Link to="/">APP 主页面</Link></li>
</ul>
</div>
} export default inject('store')(observer(CompnentA));

inject('store')(observer(CompnentA)) => 可以理解为将store 注入 可监测的 CompnentA 中。

点击事件方法 addCount 它会触发 store 里面的 action 方法,

    addCount(payload) {
this.count += payload;
}

action 方法 修改 state上的数据,页面上的数据会及时刷新。

从这里我们就可以明显看出与redux的不同,不需要通过reducer 去根据不同的type 来修改state 上的数据,而是直接通过action方法直接修改。

4.其他页面使用mobx的姿势

export default inject('store')(observer(Bar)); => 可以理解为将store 注入 可监测的 页面 Bar 中。

    import React  from 'react';
import { inject, observer } from 'mobx-react'; // 组件B中获取count的值
function Bar(props) {
const { count, pageName} = props.store.storeOne
return <div>
<h2>Bar</h2>
<p>count: {count}</p>
<p>pageName: {pageName}</p>
</div>
} export default inject('store')(observer(Bar));

5. create-react-app 生成的脚手架不支持@ 装饰器语法的方案。

  1. package.json 修改启动命令
"scripts": {
"start": "PORT=8000 react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
},
  1. 安装插件,
npm install customize-cra react-app-rewired @babel/plugin-proposal-decorators --save

  1. 在src下 新建文件 config-overrides.js
    const{override,addDecoratorsLegacy}=require('customize-cra');
module.exports=override(addDecoratorsLegacy());

整体效果图片,如下

上面的演示代码已上传 [github] (https://github.com/adouwt/redux-mobx), 如有错误,敬请指出,如需转载清说明出处。感谢阅读

redux和mobx入门使用的更多相关文章

  1. MobX入门

    MobX入门 本文尝试解释MobX是如何运作的.我们将用MobX创建一个小案例.如果你正在找靠谱的MobX文档,可以去看官方文档. 什么是MobX 官方文档的解释:简洁,易扩展的状态管理.简单来说,M ...

  2. 谈谈 Redux 与 Mobx 思想的适用场景

    谈谈 Redux 与 Mobx 思想的适用场景 Redux 和 Mobx 都是当下比较火热的数据流模型,一个背靠函数式,似乎成为了开源界标配,一个基于面向对象,低调的前行. 函数式 vs 面向对象 首 ...

  3. redux VS mobx (装饰器配合使用)

    前言:redux和mobx都是状态管理器,避免父级到子级再到子子级嵌套单向数据流,可以逻辑清晰的管理更新共享数据.(刷新页面redux储蓄数据即消失) 配置使用装饰器(使用高阶函数包装你的组件): n ...

  4. redux和mobx比较(二)

    Redux Redux 是 JavaScript 状态容器,提供可预测化的状态管理. 三大核心 在 Redux 中,最为核心的概念就是 action .reducer.store 以及 state,那 ...

  5. redux和mobx比较(一)

    Redux vs Mobx 那么具体到这两种模型,又有一些特定的优缺点呈现出来,先谈谈 Redux 的优势: 数据流流动很自然,因为任何 dispatch 都会导致广播,需要依据对象引用是否变化来控制 ...

  6. 在react项目中使用redux or mobx?

    主要比较参数: 库体积,打包项目体积 开发体验 性能对比 在对比参数前首先分析一下redux和mobx的设计模式,redux和mobx都没有使用传统的mvc/mvvm形式,而且他们使用flux结构也略 ...

  7. 【译】Redux 还是 Mobx,让我来解决你的困惑!

    原文地址:Redux or MobX: An attempt to dissolve the Confusion 原文作者:rwieruch 我在去年大量的使用了 Redux,但我最近都在使用 Mob ...

  8. vuex、redux、mobx 对比

    出处:https://www.w3cplus.com/javascript/talk-about-front-end-state-management.html 其实大部分概念都差不多,只不过VUEX ...

  9. Redux 和 mobx的区别

    Redux: Redux将数据保存在单一store中,Mobx将数据保存在分散的多个store中 Redux需要手动处理变化后的操作,Mobx使用observable保存数据,数据变化后自动处理响应的 ...

随机推荐

  1. Python2021哔哩哔哩视频爬取

    一.找到想要爬取的视频,进入网页源代码 在网页源代码里面可以很容易的找到视频各种清晰度的源地址 二.对地址发送请求 如果对视频源地址发送get请求会返回403 通过按F12进入开发者工具分析 发现并不 ...

  2. 爬虫必知必会(6)_提升scrapy框架爬取数据的效率之配置篇

    如何提升scrapy爬取数据的效率:只需要将如下五个步骤配置在配置文件中即可 增加并发:默认scrapy开启的并发线程为32个,可以适当进行增加.在settings配置文件中修改CONCURRENT_ ...

  3. 基于ABP框架的SignalR,使用Winform程序进行功能测试

    在ABP框架里面,默认会带入SignalR消息处理技术,它同时也是ABP框架里面实时消息处理.事件/通知处理的一个实现方式,SignalR消息处理本身就是一个实时很好的处理方案,我在之前在我的Winf ...

  4. Java基础:特性write once;run anywhere!

    三高:高可用 高性能 高并发 特性: 简单性 面向对象:万物皆为对象 可移植性 高性能 分布式 动态性 多线程 安全性 健壮性 Java三大版本 javaSE:标准版(桌面程序,控制台) javaME ...

  5. 2019HDU多校第七场 HDU6646 A + B = C 【模拟】

    一.题目 A + B = C 二.分析 比较考验码力的题. 对于$c$,因为首位肯定不为0,那么$a$或者$b$至少有一个最高位是和$c$平齐的,或者少一位(相当于$a$+$b$进位得到). 那么这里 ...

  6. css实现一个电影卡片

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  7. 如何动态生成EasyUI的表头

    需求 前几天遇到了这样一个需求,在页面上展示一组数据,但是表头不固定,需要动态加载出来.比如这次查询表头有[姓名][年龄],可能下次查询表头就变成了[姓名][年龄][性别]. 思路简介 我刚刚接手这个 ...

  8. Hive中静态分区和动态分区总结

    目录 背景 第一部分 静态分区 第二部分 动态分区 第三部分 两者的比较 第四部分 动态分区使用的问题 参考文献及资料 背景 在Hive中有两种类型的分区:静态分区(Static Partitioni ...

  9. java例题_50 题目:有五个学生,每个学生有 3 门课的成绩,从键盘输入以上数据(包括学生号,姓名,三门课成 绩),计算出平均成绩,将原有的数据和计算出的平均分数存放在磁盘文件"stud"中。

    1 /*50 [程序 50 文件 IO] 2 题目:有五个学生,每个学生有 3 门课的成绩,从键盘输入以上数据(包括学生号,姓名,三门课成 3 绩),计算出平均成绩,将原有的数据和计算出的平均分数存放 ...

  10. 前端富文本编辑器vue + tinymce

    之前有项目需要用到富文本编辑器,在网上找了好几个后,最终选择了这个功能强大,扩展性强的tinymce tinymce中文文档地址(不全):http://tinymce.ax-z.cn/ tinymce ...