MobX 在 React Native开发中的应用
2017-07-14 13:57
239 查看
MobX 是一款精准的状态管理工具库,如果你在 React 和 React Native 应用中使用过 Flux、Alt、Redux 和 Reflux,那毫不犹豫地说,MobX 的简单性将成为你状态管理的不二之选。
加入我们要实现这样一个功能:创建一个新的列表,向列表中加入新的条目并刷新,这就用到了MobX的状态管理。
现在我们项目配置好了,可以写代码了。不过在开发之前需要对
@observable: 使用此标签监控要检测的数据;
@observer: 使用此标签监控当数据变化是要更新的Component(组件类)
@action:使用此标签监控数据改变的自定义方法(当在需要数据改变的时候执行此自定义方法,那么View层也会跟着自动变化,默认此View层已经使用@observer标签监控)
从 mobx 导入 observable – observable
可以给存在的数据结构如对象、数组和类增加可观察的能力。简单地给类属性增加一个 @observable 装饰器(下一代
ECMAScript),或者调用 observable 或 extendObservable 函数(ES5);
创建一个叫做 ObservableListStore 的类;
创建一个可观察的数组 list;
创建三个操作列表数组的方法;
创建一个 ObservableListStore 的实例 observableListStore;
导出 observableListStore
现在已经用了存储器,我们修改项目的入口文件,使用存储,创建导航。
现在,我们来创建应用组件。实现对数据的操作。
从 mobx-react/native 导入 observer;
使用 @observer 装饰器描述类,确保相关数组变化后组件独立地重渲染;
导入已经创建好的组件 NewItem。这是我们要增加新条目时转向的组件;
在 addListItem中,把 this.state.text 传入this.props.store.addListItem。在与输入框绑定的 updateText 中会更新this.state.text;
在 removeListItem 中调用 this.props.store.removeListItem 并传入条目;
在 addItemToList 中调用 this.props.navigator.push,传入条目和数组存储两个参数;
在 render 方法中,通过属性解构数据存储:
8.在 render 方法中,也创建了界面,并绑定了类的方法
如果你之前使用过MobX,那么相信在React Native使用同样简单。
加入我们要实现这样一个功能:创建一个新的列表,向列表中加入新的条目并刷新,这就用到了MobX的状态管理。
环境配置
首先,我们为MobX配置相关的环境支持。1.npm i mobx mobx-react --save //引入mobx 2.npm i babel-plugin-transform-decorators-legacy babel-preset-react-native-stage-0 --save-dev //能够使用@标签 3.在项目目录下找到.babelrc文件,并修改为{ "presets": ["react-native"], "plugins": ["transform-decorators-legacy"] }
现在我们项目配置好了,可以写代码了。不过在开发之前需要对
mobx标签
mobx常用的标签做一个解释。@observable: 使用此标签监控要检测的数据;
@observer: 使用此标签监控当数据变化是要更新的Component(组件类)
@action:使用此标签监控数据改变的自定义方法(当在需要数据改变的时候执行此自定义方法,那么View层也会跟着自动变化,默认此View层已经使用@observer标签监控)
mobx实例1
下面实现一个使用mobx实现一个简单的数据复制更新功能。import React, {Component} from 'react'; import { View, StyleSheet, ScrollView, Text, } from 'react-native'; /* * 引入头文件 * */ import {observable, action} from 'mobx'; import {observer} from 'mobx-react/native'; /* * 添加数据 * */ const datas = [ {name:'苹果',count:0}, {name:'梨',count:0}, {name:'香蕉',count:0}, {name:'草莓',count:0}, {name:'橘子',count:0}, ]; /* * 对整个列表添加观察,观察列表个数的变化 * */ @observer export default class MobxTestSecond extends Component { /* * 数据管理器 * */ dataManager = new DataSource(); componentWillMount() { /* * 赋值初始数据 * */ this.dataManager.replace(datas); } /* * 添加一个新的Item * */ addItem = () => { let item = {name:'西瓜',count:0}; this.dataManager.addItem(item) }; /* * 删除第一个Item * */ deleteItem = () => { this.dataManager.deleteItem(0); }; render() { return ( <View style={styles.container}> <View style={styles.addItemView}> <Text style={styles.addItem} onPress={this.addItem}>增加</Text> <Text style={styles.addItem} onPress={this.deleteItem}>删除</Text> </View> <ScrollView> { this.dataManager.dataSource.slice(0).map((item,i)=> <ItemView key = {i} item = {item}/>) } </ScrollView> </View> ); } } /* * 对每一个Item添加观察,改变个数 * */ @observer class ItemView extends Component { countAdd = () => { this.props.item.add(); }; countDec = () => { this.props.item.dec(); }; render() { const {item} = this.props; return ( <View style={styles.itemContainer}> <Text>{item.name}</Text> <Text>{item.count}</Text> <Text style={styles.btn} onPress={this.countAdd}> + </Text> <Text style={styles.btn} onPress={this.countDec}> - </Text> </View> ); } } /* * 整个列表页数据管理器 * */ class DataSource { // 本地数据源 @observable dataSource = []; // 添加初始数据 @action replace = (items) => { // 1. 清空原数据 this.dataSource.splice(0, this.dataSource.length); // 2. 加载新数据 items.map((item, i) => { this.dataSource.push(new Item(item)); }); }; // 添加新数据 @action addItem = (item) => { this.dataSource.unshift(new Item(item)); }; // 删除一条数据 @action deleteItem = (idx) => { this.dataSource.splice(idx, 1); }; } /* * 单条Item数据管理器 * */ class Item { /* * 商品名称(此值是不变的所以不需要检测此值) * */ name; /* * 监控商品个数 * */ @observable count; constructor(item) { this.name = item.name; this.count = item.count; }; /* * 商品个数+1 * */ @action add = () => { this.count += 1; }; /* * 商品个数-1 * */ @action dec= () => { this.count > 0 && (this.count -= 1); }; }
案例2
新建一个 listStore.js文件。从 mobx 导入 observable – observable
可以给存在的数据结构如对象、数组和类增加可观察的能力。简单地给类属性增加一个 @observable 装饰器(下一代
ECMAScript),或者调用 observable 或 extendObservable 函数(ES5);
创建一个叫做 ObservableListStore 的类;
创建一个可观察的数组 list;
创建三个操作列表数组的方法;
创建一个 ObservableListStore 的实例 observableListStore;
导出 observableListStore
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((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
现在已经用了存储器,我们修改项目的入口文件,使用存储,创建导航。
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)
现在,我们来创建应用组件。实现对数据的操作。
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> <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 && <TextInput style={styles.input} onChangeText={(text) => this.updateText(text)} />} </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' }, item: { color: '#156e9a', fontSize: 18, flex: 3, padding: 20 }, deleteItem: { flex: 1, padding: 20, color: '#a3a3a3', 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: { height: 70, backgroundColor: '#f2f2f2', padding: 20, color: '#156e9a' }, noList: { flex: 1, justifyContent: 'center', alignItems: 'center' }, noListText: { fontSize: 22, color: '#156e9a' }, }) export default TodoList
从 mobx-react/native 导入 observer;
使用 @observer 装饰器描述类,确保相关数组变化后组件独立地重渲染;
导入已经创建好的组件 NewItem。这是我们要增加新条目时转向的组件;
在 addListItem中,把 this.state.text 传入this.props.store.addListItem。在与输入框绑定的 updateText 中会更新this.state.text;
在 removeListItem 中调用 this.props.store.removeListItem 并传入条目;
在 addItemToList 中调用 this.props.navigator.push,传入条目和数组存储两个参数;
在 render 方法中,通过属性解构数据存储:
const { list } = this.props.store
8.在 render 方法中,也创建了界面,并绑定了类的方法
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
如果你之前使用过MobX,那么相信在React Native使用同样简单。
相关文章推荐
- 【React Native开发】React Native应用设备运行(Running)以及调试(Debugging)(3)
- Windows下使用AndroidStudio+ReactNative开发Android应用
- React-Native 之Android应用开发踩坑纪 (一)————windows环境下配置
- Android 原生应用嵌入React-Native模块开发-环境配置及填坑记
- React Native跨平台移动应用学习与开发(一) 环境的搭建
- 适用于UWP应用开发的开源React Native插件
- react-native + as <react-native嵌入原生应用开发>
- 【React Native开发】React Native应用设备执行(Running)以及调试(Debugging)(3)
- react-native开发swift的ios应用,使用callback通信方式回调键值对组
- 使用 MobX 开发 React Native 应用
- Windows下使用AndroidStudio+ReactNative开发Android应用
- Facebook 开源安卓版 React Native,开发者可将相同代码用于网页和 iOS 应用开发
- Windows下使用AndroidStudio+ReactNative开发Android应用
- ios 原生应用和React native 结合开发1.环境搭建
- React-native开发系列(一)---NavigatorIOS应用
- React-Native开发总结-react-navigation应用与实践
- ReactNative 开发Android应用
- 更新来了,【React Native 应用开发指南】PDF
- 【REACT NATIVE 跨平台应用开发】环境搭建问题记录&&XCODE7模拟器上COMMAND+R失效的几种替换方法
- 2.android 原生应用和React native 结合开发.环境搭建