react 关注的状态(state)到视图(view)的问题。而 mobx 关注的是状态仓库(store)到的状态(state)的问题。
首先,让我们来新建一个ReactNative工程
react-native init ReactNativeMobX
接着,安装我们所需要的依赖库:mobx 和 mobx-react
npm i mobx mobx-react --save
为了使用ES7的语法,我们还需要安装两个babel插件
npm i babel-plugin-transform-decorators-legacy babel-preset-react-native-stage-0 --save-dev
现在你的工程目录下应该有.babelrc文件(如果没有可自行创建),修改文件的内容为:
{
"presets": ["react-native"],
"plugins": ["transform-decorators-legacy"]
}
关于babel的更多知识可参考点我查看详细
至此,你的mobx环境就搭建好了,接下来让我们来编写相应的代码
在程序的根目录下创建一个名app的文件夹,在app路径下创建一个名为mobx的文件夹,在mobx文件夹中创建一个名为listStore.js的文件:
import {observable} from 'mobx';
let index = 0;
class ObservableListStore {
@observable list = [];
addListItem = (item) => {
this.list.push({
name: item,
items: [],
index
});
index++;
};
removeListItem = (item) => {
this.list = this.list.filter((e) => {
return e.index !== item.index;
});
};
addItem(item, name){
this.list.forEach((e) => {
if (e.index === item.index){
e.items.push(name);
}
})
};
}
const observableListStore = new ObservableListStore();
export default observableListStore;
现在,我们创建了一个状态仓库(store),接下来我们来修改根目录下的index.android.js(index.ios.js)文件,让它应用我们之前创建的store,然后创建一个navigation
import React, { Component } from 'react';
import App from './app/App';
import ListStore from './app/mobx/listStore';
import {
AppRegistry,
Navigator
} from 'react-native';
export default class MobxDemo extends Component {
renderScene = (route, navigator) => {
return ;
};
configureScene = (route, routeStack) => {
if (route.type === 'Modal'){
return Navigator.SceneConfigs.FloatFromBottom;
}
return Navigator.SceneConfigs.PushFromRight;
}
render(){
return (
);
}
}
AppRegistry.registerComponent('MobxDemo', () => MobxDemo);
我们做的很简单,创建一个navigator,并初始让其跳转至App组件(稍后介绍),并为其传入ListStore
现在,让我们来创建App组件。它将是一个非常大的组件,但是现在,我们仅仅是搭建一个基础的列表接口,以便让我们可以对列表的条目可以进行操作(增删等)。在这里,store作为App的一个props传入进来,我们就可以很方便地使用它:
import React, { Component } from 'react'
import { View, Text, TextInput, TouchableHighlight, StyleSheet } from 'react-native'
import {observer} from 'mobx-react/native'
import NewItem from './NewItem'
@observer
class TodoList extends Component {
constructor () {
super()
this.state = {
text: '',
showInput: false
}
}
toggleInput () {
this.setState({ showInput: !this.state.showInput })
}
addListItem () {
this.props.store.addListItem(this.state.text)
this.setState({
text: '',
showInput: !this.state.showInput
})
}
removeListItem (item) {
this.props.store.removeListItem(item)
}
updateText (text) {
this.setState({text})
}
addItemToList (item) {
this.props.navigator.push({
component: NewItem,
type: 'Modal',
passProps: {
item,
store: this.props.store
}
})
}
render() {
const { showInput } = this.state
const { list } = this.props.store
return (
My List App
{!list.length ? : null}
{list.map((l, i) => {
return
{l.name.toUpperCase()}
Remove
})}
{!showInput &&
{this.state.text === '' && '+ New List'}
{this.state.text !== '' && '+ Add New List Item'}
}
{showInput &&
this.updateText(text)} />
确定
}
);
}
}
const NoList = () => (
No List, Add List To Get Started
)
const styles = StyleSheet.create({
itemContainer: {
borderBottomWidth: 1,
borderBottomColor: '#ededed',
flexDirection: 'row',
justifyContent:'space-between'
},
item: {
color: '#156e9a',
fontSize: 18,
flex: 1,
padding: 20
},
deleteItem: {
padding: 20,
color: 'rgba(240,1,7,1.0)',
fontWeight: 'bold',
marginTop: 3
},
button: {
height: 70,
justifyContent: 'center',
alignItems: 'center',
borderTopWidth: 1,
borderTopColor: '#156e9a'
},
buttonText: {
color: '#156e9a',
fontWeight: 'bold'
},
heading: {
height: 80,
justifyContent: 'center',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#156e9a'
},
headingText: {
color: '#156e9a',
fontWeight: 'bold'
},
input: {
flex:1,
height: 70,
backgroundColor: '#f2f2f2',
padding: 20,
color: '#156e9a'
},
noList: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
noListText: {
fontSize: 22,
color: '#156e9a'
},
sureBtn: {
width: 70,
height: 70,
justifyContent: 'center',
alignItems: 'center',
borderTopWidth: 1,
borderColor: '#ededed'
},
})
export default TodoList
最后,让我们来创建最后一个组件NewItem
import React, { Component } from 'react'
import { View, Text, StyleSheet, TextInput, TouchableHighlight } from 'react-native'
class NewItem extends Component {
constructor (props) {
super(props)
this.state = {
newItem: ''
}
}
addItem () {
if (this.state.newItem === '') return
this.props.store.addItem(this.props.item, this.state.newItem)
this.setState({
newItem: ''
})
}
updateNewItem (text) {
this.setState({
newItem: text
})
}
render () {
const { item } = this.props
return (
{item.name}
×
{!item.items.length && }
{item.items.length ? : }
this.updateNewItem(text)}
style={styles.input} />
Add
)
}
}
const NoItems = () => (
No Items, Add Items To Get Started
)
const Items = ({items}) => (
{items.map((item, i) => {
return • {item}
})
}
)
const styles = StyleSheet.create({
heading: {
height: 80,
justifyContent: 'center',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#156e9a'
},
headingText: {
color: '#156e9a',
fontWeight: 'bold'
},
input: {
height: 70,
backgroundColor: '#ededed',
padding: 20,
flex: 1
},
button: {
width: 70,
height: 70,
justifyContent: 'center',
alignItems: 'center',
borderTopWidth: 1,
borderColor: '#ededed'
},
closeButton: {
position: 'absolute',
right: 17,
top: 18,
fontSize: 36
},
noItem: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
noItemText: {
fontSize: 22,
color: '#156e9a'
},
item: {
color: '#156e9a',
padding: 10,
fontSize: 20,
paddingLeft: 20
}
})
export default NewItem
至此,mobx相关代码编写完毕,我们可以看到mobx以最直接的方式来管理我们的状态,即我们开始说的 mobx 关注的是状态仓库(store)到的状态(state)的问题。