最近在學(xué)習(xí)React的架構(gòu)女责,看了很火的Redux,然而學(xué)習(xí)Redux的過程異常痛苦创译。
于是乎發(fā)現(xiàn)了Redux作者推薦的另一種狀態(tài)管理庫抵知,Mobx
unhappy with redux? try mobx //Redux作者的原話
用Mobx做狀態(tài)管理真的是爽爆了,簡單易懂,大大提升編碼效率刷喜,替代redux的首選,廢話不多說残制,進(jìn)入正題。
1.初始化項(xiàng)目
首先創(chuàng)建一個新的React Native項(xiàng)目吱肌,打開終端輸入
react-native init ReactNativeMobx
項(xiàng)目創(chuàng)建成功后,安裝mobx和mobx-react
cd ReactNativeMobx
npm i mobx mobx-react --save
接下來在根目錄下創(chuàng)建名為app的文件夾仰禽,在app文件夾下創(chuàng)建名為mobx的文件夾氮墨,在mobx文件夾下創(chuàng)建listStore.js,在app文件夾下創(chuàng)建App.js(程序首頁)和NewItem.js(程序二級界面)如下圖
2.代碼部分
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) {
console.log('item:::', item)
this.list = this.list.filter((l) => {
return l.index !== item.index
})
}
addItem(item, name) {
this.list.forEach((l) => {
if (l.index === item.index) {
l.items.push(name)
}
})
}
}
const observableListStore = new ObservableListStore()
export default observableListStore
上面代碼中
1.引用observable
2.創(chuàng)建ObservableListStore類
3.@observable list[]吐葵,監(jiān)聽list的變化
4.三個方法规揪,添加列表,刪除列表温峭,添加一條數(shù)據(jù)
5.導(dǎo)出ObservableListStore
接下來寫入口index代碼,憑你的喜好打開index.android.js或者index.ios.js猛铅,
import React, { Component } from 'react'
import App from './app/App'
import ListStore from './app/mobx/listStore'
import {
AppRegistry,
Navigator
} from 'react-native'
class ReactNativeMobX extends Component {
renderScene (route, navigator) {
return <route.component {...route.passProps} navigator={navigator} />
}
configureScene (route, routeStack) {
if (route.type === 'Modal') {
return Navigator.SceneConfigs.FloatFromBottom
}
return Navigator.SceneConfigs.PushFromRight
}
render () {
return (
<Navigator
configureScene={this.configureScene.bind(this)}
renderScene={this.renderScene.bind(this)}
initialRoute={{
component: App,
passProps: {
store: ListStore
}
}} />
)
}
}
AppRegistry.registerComponent('ReactNativeMobx', () => ReactNativeMobX)
以上重點(diǎn)為Navigator通過passProps將ListStore傳入,其余代碼為Navigator的初始化凤藏。
接下來寫我們程序首頁App.js的代碼
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 (
<View style={{flex:1}}>
<View style={styles.heading}>
<Text style={styles.headingText}>My List App</Text>
</View>
{!list.length ? <NoList /> : null}
<View style={{flex:1}}>
{list.map((l, i) => {
return <View key={i} style={styles.itemContainer}>
<Text
style={styles.item}
onPress={this.addItemToList.bind(this, l)}>{l.name.toUpperCase()}</Text>
<Text
style={styles.deleteItem}
onPress={this.removeListItem.bind(this, l)}>Remove</Text>
</View>
})}
</View>
{!showInput && <TouchableHighlight
underlayColor='transparent'
onPress={
this.state.text === '' ? this.toggleInput.bind(this)
: this.addListItem.bind(this, this.state.text)
}
style={styles.button}
>
<Text style={styles.buttonText}>
{this.state.text === '' && '+ New List'}
{this.state.text !== '' && '+ Add New List Item'}
</Text>
</TouchableHighlight>}
{showInput && <View style={{flexDirection: 'row'}}>
<TextInput
style={styles.input}
onChangeText={(text) => this.updateText(text)} />
<TouchableHighlight
style={styles.sureBtn}
onPress={
this.state.text === '' ? this.toggleInput.bind(this)
: this.addListItem.bind(this, this.state.text)
} >
<Text>確定</Text>
</TouchableHighlight>
</View>}
</View>
);
}
}
const NoList = () => (
<View style={styles.noList}>
<Text style={styles.noListText}>No List, Add List To Get Started</Text>
</View>
)
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.js代碼
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 (
<View style={{flex: 1}}>
<View style={styles.heading}>
<Text style={styles.headingText}>{item.name}</Text>
<Text
onPress={this.props.navigator.pop}
style={styles.closeButton}>×</Text>
</View>
{!item.items.length && <NoItems />}
{item.items.length ? <Items items={item.items} /> : <View />}
<View style={{flexDirection: 'row'}}>
<TextInput
value={this.state.newItem}
onChangeText={(text) => this.updateNewItem(text)}
style={styles.input} />
<TouchableHighlight
onPress={this.addItem.bind(this)}
style={styles.button}>
<Text>Add</Text>
</TouchableHighlight>
</View>
</View>
)
}
}
const NoItems = () => (
<View style={styles.noItem}>
<Text style={styles.noItemText}>No Items, Add Items To Get Started</Text>
</View>
)
const Items = ({items}) => (
<View style={{flex: 1, paddingTop: 10}}>
{items.map((item, i) => {
return <Text style={styles.item} key={i}>? {item}</Text>
})
}
</View>
)
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
以上奸忽,所有代碼直接復(fù)制粘貼就OK