加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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>
);
}
}




********** 5)实战 -- 首页(分页列表) **********************

没记笔记


********** 6)实战 -- 购物车(联动) **********************

没记笔记


********** 7)高级 -- 计时器 **********************

没记笔记


********** 8)高级 -- autosave **********************

没记笔记


********** 9)高级 -- Swiper优化 **********************

没记笔记





mobx与redux比较


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:大型、持续较久的项目,分工细致的团队,编辑器等涉及数据回溯的功能

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读