安装遇到的问题:
Mbox的装饰器语法为es7语法。所以需要提供babel支持。
1 需要安装transform-decorators-legacy。
Npm install babel-plugin-transform-decorators –save-dev
Npm install babel-preset- stage-1
Npm install babel-preset- es2015
2 需要在根目录下新建一个.babelrc文件。
{
"presets": ["es2015", "stage-1","react"]
"plugins": ["transform-decorators-legacy"]
}
安装教程https://github.com/wulibaibao/react-mobx-demo
利用官方推荐的第二种办法:Rewire create-react-app to use MobX
1 基本介绍
mobx ------该模块通过提供诸如obersevable,autorun等基础函数和语法实现数据的可监控和自动执行
常用的函数:
-----------------
Obersevable: 让数据可监控。类似vue中的state。用来控制数据
Action:数据响应。类似vue中的mutaion ,派发动作。实现数据的操作
Comuted:数据的筛选。类似vue中的getters。
mobx-react :连接react组件和mbox中store数据的桥梁。
常见api:
Oberser --à让某个组件成为观察者。
注意1 单独组件如果要引用store中的数据。需要通过@inject(store)
import { observable, computed } from "mobx";
import {Provider}from "mobx-react";
class Store{
@observable
todo=[{title:"初始标题",done:false},{title:"标题2",done:true}];
@observable count=0;
const store=new Store()
}
const store=new Store()
<Provider store={store}>
<App />
</Provider>
组件中
@inject("store") =è注意只接受store
@observer class App extends Component{
render(){
let count=this,props. store.count;
return(<div>{count}</div>)
}
}
2注意@action中函数的this指向问题。
class Store{
@action changeTitle=({index,title})=>{
console.log(title)
this.todo[index].title=title; 这里this指向是Store对象,箭头函数,锁定this对象
console.log(toJS(this.todo))
}
@action changeTitle({index,title}){
console.log(title)
this.todo[index].title=title; 这里this指向是单击时的dom对象
console.log(toJS(this.todo))
}
}
组件中:
@observer class App extends Component{
render(){
let {count,add,todo,changeTitle}=this.props.store
}
<input type="button" value="修改" onClick={()=>{ changeTitle({index:0,title:"更新后的数据"}) } }/>
}
注意;启动mbox的严格模式。在mobx4版本中已经做了改动》
4之前的版本
import {observable,action,toJS,computed,runInAction,useStrct} from "mobx"
useStrct(true)
4以后的版本
import {observable,action,toJS,computed,runInAction, configure} from "mobx"
configure({enforceActions:true})
Uncaught ReferenceError: regeneratorRuntime is not defined报错的问题:
现象:
使用 ES7 的 async/await 时报错。
解决方法:
$ npm i --save-dev babel-plugin-transform-runtime
在 .babelrc 文件中添加:
"plugins": [[
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
]]
最后.babelrc的配置:
{
"presets": ["es2015", "stage-1","react"],
"plugins": [
[
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
],
"transform-decorators-legacy"
]
}
Mobx中异步action的几种方式:
(这里一定要注意写成箭头函数的形式)
1 通过async +await异步函数结合 runInAction函数
实例:
import {observable,action,toJS,computed,runInAction,configure} from "mobx"
configure({enforeceActions:true})
class Store{
@observable articleData=[]; ====》用来获取最后的数据
@observable loading=false =====》用来显示loading状态
@action getArticleData=async()=>{ 注意这里箭头函数的写法
console.log("this:",this)
this.loading=true
console.log("异步。。。")
let res= await getData()
console.log("res:",res)
runInAction(()=>{
this.loading=false
this.articleData=res.data.data;
})
}
}
方式二:
类似redux,一个异步请求,走3个action分别代表异步请求开始。成功和错误三个状态。
这里唯一要注意的就是action必须使用箭头函数
Eg:
import {observable,action,toJS,computed,runInAction,configure,bound} from "mobx"
configure({enforeceActions:true})
class Store{
@observable articleData=[]; ====》用来获取最后的数据
@observable loading=false =====》用来显示loading状态
@action getArticleData=()=>{
this.loading=true;
console.log("getData:",getData)
getData().then(this.fetchSuccess).catch(this.fetchFail)
}
@action.bound fetchSuccess=(res=>{
console.log("res:",res)
this.loading=false;
this.articleData=res.data.data
})
@action.bound fetchFail=(err=>{
console.log("err:",err)
})
}
const getData=()=>{
return axios.get(baseUrl+"/article/list?start=0&size=20")
}
第三种:内联action的方式。
和第二种有点类似。第二种方式 fetchSuccess和fetchFail 分别抽离出来。而内联action则是直接写在一个action中。
Eg:
import {observable,action,toJS,computed,runInAction,configure,bound} from "mobx"
configure({enforeceActions:true})
@observable articleData=[];
@observable loading=false
@action getArticleData=()=>{
this.loading=true;
console.log("getData:",getData)
getData().then(action('fetchSuccess',res=>{
this.loading=false;
this.articleData=res.data.data
})).catch(action('fetchFail',err=>{
console.log("err:",err)
}))
}
注意。这里action需要给加上名称。
错误日志:
Leading decorators must be attached to a class declaration
原因:
@inject("store");装饰器后面不能加分号。
错误写法:
@inject("store"); //注意这里的分号
@observer class AuthorizedRoute extends Component{
render(){
return(
<div>
21231231
</div>
)
}
}
正确写法:
@inject("store") //注意这里的分号
@observer class AuthorizedRoute extends Component{
render(){
return(
<div>
21231231
</div>
)
}
}
装饰器的写法规则 @装饰器1 @装饰器2 @装饰器3