最近不断在博客中的看到MoBx这个东西,仔细研究下确实比Redux优势明显,代码也不再冗余。使用过Rxjs的开发者可能更有感觉。主要模式:(view层)观察者, (store)被观察者,在view层store可以被直接更改,但是最好还是要使用严格模式,使用action来更改store。
下面写一个简单的例子来入个门
- 下载相关依赖包
yarn add mobx mobx-react
- mobx使用了ES7的装饰器,使用create-react-app 创建项目的话使用的是babel 6.x.x编译的,下面让babel支持对装饰器的编译
Babel >= 7.x
yarn add @babel/plugin-proposal-decorators -D
// package.json配置babel
{
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
]
}
babel@6.x
yarn add babel-plugin-transform-decorators-legacy -D
// 在package.json中进行配置plugins, 如果插件为多个,"transform-decorators-legacy"应该放到第一个
"babel": {
"presets": [
"react-app"
],
"plugins": [
"transform-decorators-legacy"
]
},
3.进行store的代码编写
javascript 代码
import {observable, action, useStrict, computed} from 'mobx';
useStrict(true); //使用严格模式,防止直接在view层修改store中的数据
class Store {
@observable todos = [{ //todos即为被观察的数据
title: 'todo标题',
done: false
}, {
title: '标题2',
done: true
}]
@action changeTodoTitle({index, title}) { //用来修改todos的action
this.todos[index].title = title;
}
@computed get unfinishedTodos() { // 相当于vue中的计算属性,可以对todos进行过滤并返回,可缓存,不会产生不必要的的重渲染
return this.todos.filter((todo) => todo.done === false);
}
@computed get finishedTodos() {
return this.todos.filter((item) => item.done);
}
}
export default new Store();
- store创建好后,接下来先搭建路由,这里使用react-router4,浏览中只需使用 react-router-dom便可
javascript 代码
yarn add react-router-dom
写一个路由组件
javascript 代码
import {Switch, Route} from 'react-router-dom';
import React from 'react';
import App from '../App';
import TestMobx from '../views/TestMobx'; // 要测试的目标组件
import TestMobx2 from '../views/TestMobx2';
import store from '../Store/store'; // 导入store
const Routes = () => (
<Switch>
<Route exact path='/' component={App}></Route>
// 将store通过Route中render的方式添加进去,这样在TestMobx组件中便可以通过this.props.store来进行访问
<Route path='/mobx' render={(props) => <TestMobx {...props} store={store}></TestMobx>}></Route>
<Route path='/mobx2' render={(props) => <TestMobx2 {...props} store={store}></TestMobx2>}></Route>
</Switch>
)
export default Routes;
5.完成路由后,接下来使路由生效,在入口index.js中进行配置
javascript 代码
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import {BrowserRouter} from 'react-router-dom';
import Routes from './router/index'; // 导入配置的路由
ReactDOM.render(
<BrowserRouter>
<Routes />
</BrowserRouter>,
document.getElementById('root')
);
registerServiceWorker();
- 最后是目标组件TestMobx.js
javascript 代码
import React, {Component} from 'react';
import {observer} from 'mobx-react';
@observer
class TestMobx extends Component {
constructor(props) {
super(props);
console.log(this.props); // 包含路由信息以及store
}
render() {
return (
<div>
<h4>未完成事项</h4>
<ul>
{
this.props.store.unfinishedTodos.map((item, index) => <li key={index}>{item.title}</li>)
}
</ul>
<h4>已完成事项</h4>
<ul>
{
this.props.store.finishedTodos.map((item, index) => <li key={index}>{item.title}</li>)
}
</ul>
<div>
<input type="button" onClick={() => this.props.store.changeTodoTitle({index: 0, title: '修改标题'})} value='点我' />
</div>
</div>
)
}
}
export default TestMobx;
最后不得不说代码结构更清晰了,不再像redux那样,store需要有好几个文件。