React Native -- mobx
发布时间:2020-12-15 07:20:56 所属栏目:百科 来源:网络整理
导读:React Native -- mobx: mobx是一个小巧优雅的库,可以帮助我们很好的管理前端状态的变更。 其实mobx提供的不只是Component的自动更新,mobx本身提供的是一种自动更新的机制。 ----------------------------------------------------------------------------
React Native -- mobx: mobx是一个小巧优雅的库,可以帮助我们很好的管理前端状态的变更。 其实mobx提供的不只是Component的自动更新,mobx本身提供的是一种自动更新的机制。 --------------------------------------------------------------------------------------------------------------------- 下面是看这个视频(作者:天地之灵)记录的笔记:http://v.youku.com/v_show/id_XMjQ4NTA4OTUwOA==.html?spm=a2hzp.8253869.0.0&from=y1.7-2#paction 视频中项目的GitHub地址:https://github.com/tdzl2003/mobx-lesson-20170122 1)概念简介 -- observable,computed,action,autorun,map 2)入门 -- Counter 3)入门 -- TODO List 4)实战 -- 登录注册(表单) 5)实战 -- 首页(分页列表) 6)实战 -- 购物车(联动) 7)高级 -- 计时器 8)高级 -- autosave 9)高级 -- Swiper优化 ================================================================================ 安装需要的依赖:mobx 和 mobx-react。 npm i mobx mobx-react --save 我们也要安装一些 babel 插件,以支持 ES7 的 decorator 特性: npm i babel-plugin-transform-decorators-legacy babel-preset-react-native-stage-0 --save-dev 现在,创建一个 .babelrc 文件配置 babel 插件: { 'presets': ['react-native'], 'plugins': ['transform-decorators-legacy'] } 因为我们编写的是一个自定义 .babelrc 文件,所有只需要 react-native 的 preset。 配置 react-native 的 preset,还有指定一些先期运行的插件(我们这里是 transform-decorators-legacy 插件)。 ====================================================================================== *********** 1)概念简介 demo1 -- observable的使用 ****************************** import { observable,autorun} from 'mobx'; export default function demo1() { const value = observable(0); autorun(() => { console.log(`value is: ${value.get()}`); }); value.set(2); value.set(8); value.set(-3); } *********** 1)概念简介 demo2 -- computed的使用 ****************************** import { observable,autorun} from 'mobx'; export default function demo2() { const value = observable(0); const condition = computed(() => {value.get() >= 0}); autorun(() => { console.log(`condition is: ${condition.get()}`); }); value.set(2); value.set(8); value.set(-3); } *********** 1)概念简介 demo3 -- observable Object的使用 ****************************** import { observable,autorun} from 'mobx'; export default function demo3() { // 返回一个对象 const value = observable({ foo: 0, bar: 0, get condition() { return this.foo >= 0; }, }); autorun(() => { console.log(`value.foo is: ${value.foo}`); }); autorun(() => { console.log(`value.condition is: ${value.condition}`); }); value.foo = 2; value.foo = 8; value.foo = -3; value.bar = 1; value.bar = 2; } *********** 1)概念简介 demo4 -- observable Array的使用 ************ import { observable,autorun} from 'mobx'; export default function demo4() { const value = observable([0]); autorun(() => { console.log(`value.length is: ${value.length}`); }); autorun(() => { console.log(`value[0] is: ${value[0]}`); }); value[0] = 1; value.push(2); value.push(3); value.splice(0,1); } *********** 1)概念简介 demo5 -- use class and decorator,项目中多数用到这方面的知识,上面的demo只是简单介绍 ***************** import { observable,useStrict} from 'mobx'; useStrict(true); // 使用严格规范,强制使用@action,推荐写法。 class Foo { @observable selected = 0; @observable items = []; @computed get selectedItem() { if (this.selected >= this.items.length) { return null; } return this.items[this.selected]; } @action addItem(item) { this.items.push(item); } @action removeAt(id) { this.items.splice(id,1); if (this.selected >= id) { this.selected--; } } @action removeSelected() { this.items.splice(this.selected,1); } } export default function demo5() { const foo = new Foo(); autorun(() => { console.log(`Current selected is: ${foo.selectedItem()}`); }); foo.addItem(0); foo.addItem(1); foo.addItem(2); foo.addItem(3); foo.selected = 2; foo.removeSelected(); foo.removeAt(0); } *********** 1)概念简介 demo6 -- observable map的使用,不常用 *************** import { autorun,map } from 'mobx'; export default function demo6() { const foo = map({}); autorun(() => { console.log(`map have ${map.size} keys`); }); foo.set('foo',1); foo.set('bar',1); foo.set('foo',2); foo.delete('bar'); } *********** 2)入门 -- Counter ****************** import React,{ Component } from 'react'; import { StyleSheet, View, Text, } from 'react-native'; import { observable } from 'mobx'; import { observer } from 'mobx-react/native'; const counter = observable(0); function inc() { counter.set(counter.get() + 1); } function dec() { counter.set(counter.get() - 1); } @observer export default class Counter1 extends Component { render() { return ( <View style={styles.container}> <Text style={styles.value}>{counter.get()}</Text> <Text style={styles.btn} onPress={inc}>+</Text> <Text style={styles.btn} onPress={dec}>-</Text> </View> ); } } const styles = StyleSheet.create({ container: { }, value: { }, btn: {}, }); // 第二种counter,和上面的第一种不一样,第一种的值会同时变化,第二种单独变化。 @observer export default class Counter2 extends Component { @observable counter = 0; inc = () => { ++this.counter; } dec = () => { --this.counter; } render() { return ( <View style={styles.container}> <Text style={styles.value}>{this.counter}</Text> <Text style={styles.btn} onPress={this.inc}>+</Text> <Text style={styles.btn} onPress={this.dec}>-</Text> </View> ); } } // 第三种把Text改为TextInput,用户可以输入数字 @observer export default class Counter3 extends Component { @observable counter = 0; inc = () => { ++this.counter; } dec = () => { --this.counter; } onChangeText = v => { try{ this.counter = parseInt(v); } catch(err) { } } render() { return ( <View style={styles.container}> <TextInput style={styles.value} value={`${this.counter}`} onChangeText={this.onChangeText} /> <Text style={styles.btn} onPress={this.inc}>+</Text> <Text style={styles.btn} onPress={this.dec}>-</Text> </View> ); } } ********** 3)入门 -- TODO List,自己改成ListView了,原作者用的是ScrollView ********************** import React,{Component,PropTypes,} from 'react'; import { StyleSheet, View, Text, ScrollView, TouchableOpacity, ListView, Alert, } from 'react-native'; import {observable,action} from 'mobx'; import {observer} from 'mobx-react/native'; const titles = ['Eat','Drink','Think']; class Todo { id = `${Date.now()}${Math.floor(Math.random() * 10)}`; @observable title = ''; @observable done = false; constructor(title) { this.title = title; } } function randomTodoTitle() { return titles[Math.floor(Math.random() * titles.length)]; } @observer class TodoItem extends Component { static propTypes = { data: PropTypes.instanceOf(Todo), }; @action onPress = () => { const {data} = this.props; data.done = !data.done; }; render() { const {data} = this.props; return ( <Text style={[styles.item,data.done && styles.done]} onPress={this.onPress} > {data.title} </Text> ); } } @observer export default class MobxDemoTodoList extends Component { static title = '3 - TodoList'; renderItem(data) { return (<TodoItem key={data.id} data={data}/>); } render() { return ( <ListView dataSource={this.state.dataSource} renderRow={(data,non,sid) => { return this.renderItem(data)}}/> ); } constructor(props) { super(props); const ds = new ListView.DataSource({rowHasChanged: (r1,r2) => r1 !== r2}); this.state = { dataSource: ds.cloneWithRows([ new Todo('Eat'), new Todo('D'), new Todo('T'), new Todo('Eat'), ]) }; } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'white', }, content: { justifyContent: 'center', alignItems: 'center', todo: { fontSize: 20, item: { fontSize: 30, margin: 20, color: '#f00', done: { fontSize: 30, color: '#ccc', textDecorationLine: 'line-through',// 一条横线从文本中间穿过 }, }); ********** 4)实战 -- 登录注册(表单) ********************** import validate from 'mobx-form-validate'; import { observable,toJS } from 'mobx'; // 自己定义的component import { FormProvider,FormItem,Submit } from './components/form'; /* // 第1种,不用@validate class LoginForm { @observable mobile = ''; @observable pwd = ''; @computed get mobileValidateError() { return /^1d{10}$/.test(this.mobile) ? null : 'Please input a valid phone number.'; } @computed get pwdValidateError() { return /^.+$/.test(this.pwd) ? null : 'Please input any password.'; } @computed get validateError() { return this.mobileValidateError || this.pwdValidateError; } @computed get isValid() { return !this.validateError; } } */ // 第2种 class LoginForm { @observable @validate(/^1d{10}$/,'Please input a valid phone number.') mobile = ''; @observable @validate(/^.+$/,'Please input any password.') pwd = ''; submit = async () => { // await post('/login',toJS(this)); alert(JSON.stringify(toJS(this))); } } export default class LoginPage extends Component { static title = '4 - Login Form'; form = new LoginForm(); render() { return ( <FormProvider form={this.form}> <View style={styles.container}> <FormItem name="mobile" underlineColorAndroid="transparent">Mobile<FormItem> <FormItem secureTextEntry name="pwd">Password<FormItem> <Submit onSubmit={this.form.submit}>Login</Submit> </View> </FormProvider> ); } } @observer export default class FormItem extends Component { static propTypes = { name: PropTypes.string.isRequired, form: PropTypes.object, children: PropTypes.string.isRequired, autoFocus: PropTypes.boolean, ...TextInput.propTypes, }; static contextTypes = { form: PropTypes.object, }; state = { focused: this.props.autoFocus, }; onChangeText = (text) => { const { name } = this.props; const form = this.context.form || this.props.form; form[name] = text; }; onFocus = () => { if (!this.state.focused) { this.setState({ focused: true }); } }; render() { const { name,children,form: _,...others } = this.props; const { focused } = this.state; const form = this.context.form || this.props.form; return ( <View style={styles.container}> <View style={styles.row}> <Text style={styles.label}>{children}</Text> <View style={styles.inputWrapper}> <TextInput {...others} onFocus={this.onFocus} value={form[name]} onChangeText={this.onChangeText} style={styles.input} /> </View> </View> <View> {focused && <Text style={styles.error}>{form[camelCase('validateError',name)]}</Text>} </View> </View> ); } } export default class FormProvider extends Component { static propTypes = { // eslint-disable-next-line react/forbid-prop-types form: PropTypes.object, children: PropTypes.element.isRequired, }; static childContextTypes = { form: PropTypes.object, }; getChildContext() { return { form: this.props.form, }; } render() { return React.Children.only(this.props.children); } } @observer export default class Submit extends Component { static propTypes = { children: PropTypes.string.isRequired, onSubmit: PropTypes.func, }; render() { const { children,onSubmit } = this.props; const form = this.context.form || this.props.form; return ( <TouchableOpacity style={[styles.button,form.isValid && styles.active]} disabled={!form.isValid} onPress={onSubmit} > <Text>{children}</Text> </TouchableOpacity> ); } }
没记笔记
********** 6)实战 -- 购物车(联动) ********************** 没记笔记 ********** 7)高级 -- 计时器 ********************** 没记笔记 ********** 8)高级 -- autosave ********************** 没记笔记 ********** 9)高级 -- Swiper优化 ********************** 没记笔记
1.视图更新 mobx:按需更新 redux:自上而下 2.列表支持 mobx:良好 redux:很差 3.代码量 mobx:少 redux:多 4.安全性 mobx:一般 redux:良好 5.严谨性 mobx:自由 redux:严谨 6.性能 mobx:高 redux:中等,特定场景低下 7.插件 mobx:不多、一般不用 redux:丰富、选择困难 8.异步操作 mobx:方便 redux:方便 9.主动通知 mobx:不方便 redux:部分场景不方便 10.服务端渲染 mobx:不支持 redux:支持,但有毒 11.自动化测试 mobx:一般 redux:极为方便 12.数据可回溯 mobx:不可 redux:可 13.用途 mobx:广泛,偏重数据&局部状态 redux:有毒,偏重全局性 14.适用范畴 mobx:快速迭代的项目,中小团队、分工不细、表单较多的项目 redux:大型、持续较久的项目,分工细致的团队,编辑器等涉及数据回溯的功能 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |