React-Native使用Mobx实现购物车功能


Posted in Javascript onSeptember 14, 2017

在工作中,购物车场景非常常见。本文实现基于React-Native和Mobx实现两种购物车例子。

其中,后期会加入动画等其他。本期先实现基础功能。

二:基于State实现购物车

1-:ShoppingCarPage.js

export default class ShoppingCarPage extends Component {
  static navigationOptions = {
    headerTitle : '基于State购物车',
  };

  constructor(props) {
    super(props);
    this.state = {
      allSelecte : data.isAllSelect,
      totalMoney : data.totalMoney,
    }

  };

  getMoney = (m) => {
    this.state.totalMoney=this.state.totalMoney+m;
    //this.state.totalMoney += m;
    data.totalMoney = this.state.totalMoney;
    this.setState({
      totalMoney : this.state.totalMoney
    });

    let i = 0;
    data.datas.map((item) => {
      if (item.isSelect != true) {
        i += 1;
      }
    });
    if (i == 0) {
      data.isAllSelect = true;
      this.setState({ allSelecte : true })
    }
    else {
      data.isAllSelect = false;
      this.setState({ allSelecte : false })
    }
  };

  renderItem = (item) => {
    return (
      <ShoppingItemComponent
        itemData={item}
        money={this.getMoney}
      />
    )
  };

  allSelect = () => {
    data.totalMoney = 0;
    data.isAllSelect = !data.isAllSelect;
    this.state.totalMoney = 0;
    DeviceEventEmitter.emit('allSelect', !this.state.allSelecte);
    this.setState({ allSelecte : !this.state.allSelecte })
  };

  separatorView = () => {
    return (
      <View style={{ height : 10, backgroundColor : '#e9e9e9' }}/>
    )
  };

  keyExtractor = (item) => item.name;

  render() {
    let { allSelecte, totalMoney } = this.state;
    return (
      <View style={styles.container}>
        <FlatList data={data.datas}
             ItemSeparatorComponent={this.separatorView}
             renderItem={({ item }) => this.renderItem(item)}
             keyExtractor={ this.keyExtractor }
        />
        <View style={styles.tool}>
          <View style={{ flex : 1, flexDirection : 'row', alignItems : 'center' }}>
            <TouchableOpacity style={styles.select} onPress={ this.allSelect }>
              <Image source={allSelecte ? require('./imgs/login_radio_selected.png') : require('./imgs/login_radio_normall.png')}/>
              <Text style={{ marginLeft : 3 }}>全选</Text>
            </TouchableOpacity>
            <Text style={styles.allMoneyText}>
              ¥{this.state.totalMoney}
            </Text>
          </View>
          <TouchableOpacity style={styles.balance}>
            <Text style={styles.balanceText}>去结算</Text>
          </TouchableOpacity>
        </View>


      </View>
    );
  }
}

2-:ShoppingItemComponent.js

export default class ShoppingItemComponent extends Component {

  static propTypes = {
    itemData : PropTypes.object.isRequired,
    money : PropTypes.func,
  };

  static defaultProps = {
    money : () => null,
  };

  componentDidMount() {
    this.subscription = DeviceEventEmitter.addListener('allSelect', (isSelAll) => {
      this.props.itemData.isSelect = isSelAll;
      this.setState({ isSel : isSelAll });
      if (isSelAll) {
        this.setMoney(this.state.money * this.state.selNum);
      }

    })
  };

  componentWillUnmount() {
    this.subscription && this.subscription.remove();
  };

  constructor(props) {
    super(props);
    this.state = {
      isSel : this.props.itemData.isSelect,
      selNum : this.props.itemData.count,
      money : this.props.itemData.money,
      name : this.props.itemData.name,
      description : this.props.itemData.description,
      img : this.props.itemData.img,
    }
  };

  itemSelect = (item) => {
    this.setState({isSel :!this.state.isSel},()=>{
      if (this.state.isSel) {
        this.setMoney(this.state.money * this.state.selNum)
      }
      else {
        this.setMoney(-this.state.money * this.state.selNum)
      }
    });
  };

  itemIncrease = (i) => {
    i++;
    this.setState({selNum : i},()=>{
      if (this.state.isSel) {
        this.setMoney(this.state.money)
      }else{
        this.setState({isSel :true});
        this.setMoney(this.state.money * this.state.selNum);
      }
      this.props.itemData.count = i;
    });
  };

  itemReduce = (i) => {
    if (i <= 1) {
      if(this.state.isSel){
        this.setState({isSel :!this.state.isSel});
        this.setMoney(-this.state.money)
      }
      return;
    }
    i--;
    this.setState({ selNum : i },()=>{
      if (this.state.isSel) {
        this.setMoney(-this.state.money)
      }else{
        this.setState({isSel :true});
        this.setMoney(this.state.money * this.state.selNum);
      }
      this.props.itemData.count = i;
    });

  };

  setMoney = (money) => {
    if (this.props.money) {
      this.props.money(money);
    }
  };

  render() {
    let { itemData } = this.props;
    let { isSel, selNum, money, name, description, img } = this.state;
    return (
      <View style={ styles.container }>
        <TouchableOpacity
          style={{ marginLeft : 15 }}
          onPress={() => this.itemSelect(itemData)}>
          <Image source={isSel ?
            require('./imgs/login_radio_selected.png')
            : require('./imgs/login_radio_normall.png')}/>
        </TouchableOpacity>
        <Image style={ styles.icon } source={{ uri : img }}/>
        <View style={ styles.right }>
          <Text style={ styles.nameStyle } numberOfLines={ 2 }>{ name }</Text>
          <Text style={ styles.descriptionStyle } numberOfLines={1}>{ description }</Text>
          <View style={ styles.right_bot}>
            < Text style={ styles.moneyStyle }>¥{ money }</Text>
            <View style={ styles.numControllStyle }>

              <TouchableOpacity style={ styles.reduceStyle } onPress={() => this.itemReduce(selNum)}>
                <Text style={{ color : selNum <= 1 ? 'red' : 'black' } }>-</Text>
              </TouchableOpacity>
              <View style={ styles.numberViewStyle }>
                <Text style={ styles.numberStyle }>{ selNum }</Text>
              </View>
              <TouchableOpacity style={ styles.increaseStyle } onPress={() => this.itemIncrease(selNum)}>
                <Text>+</Text>
              </TouchableOpacity>
            </View>
          </View>
        </View>
      </View>
    );
  }
}

三:基于Mobx实现购物车

1-:MobxShoppingCarPage.js

@observer
export default class MobxShoppingCarPage extends Component {
  static navigationOptions = {
    headerTitle : '基于MobX购物车',
  };

  constructor(props) {
    super(props);
    this.data = new MobxStore();
  };

  componentDidMount() {
    this.data.replace(jsonData)
  };

  @action
  allSelect = () => {
    DeviceEventEmitter.emit('allSelect', !this.data.itemData.isAllSelect);
    this.data.selectAll();
  };

  renderItem = (item) => {
    return (
      <MobxShopItemComponent itemData={ item } data={ this.data }/>
    )
  };

  separatorView = () => {
    return (
      <View style={{ height : 10, backgroundColor : '#e9e9e9' }}/>
    )
  };

  keyExtractor = (item) => item.name;

  render() {
    return (
      <View style={ styles.container }>
        <FlatList data={ this.data.itemData.datas }
             ItemSeparatorComponent={ this.separatorView }
             renderItem={ ({ item }) => this.renderItem(item) }
             keyExtractor={ this.keyExtractor }
        />
        <View style={ styles.tool }>
          <View style={{ flex : 1, flexDirection : 'row', alignItems : 'center' }}>
            <TouchableOpacity style={ styles.select } onPress={ this.allSelect }>
              <Image source={ this.data.itemData.isAllSelect ?
                require('../imgs/login_radio_selected.png')
                : require('../imgs/login_radio_normall.png') }/>
              <Text style={{ marginLeft : 3 }}>全选</Text>
            </TouchableOpacity>
            <Text style={ styles.allMoneyText }>
              ¥{ this.data.itemData.totalMoney }
            </Text>
          </View>
          <TouchableOpacity style={ styles.balance } onPress={ this.allSelect }>
            <Text style={ styles.balanceText }>去结算</Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }
}

2-:MobxShopItemComponent.js

@observer
export default class MobxShopItemComponent extends Component {

  static propTypes = {
    itemData : PropTypes.object.isRequired,
    data : PropTypes.object.isRequired,
  };

  constructor(props) {
    super(props);
    this.itemData = this.props.itemData;
  }

  componentDidMount() {
    this.subscription = DeviceEventEmitter.addListener('allSelect', (isSelAll) => {
      this.itemData.isSelect = isSelAll;
    })
  };

  componentWillUnmount() {
    this.subscription && this.subscription.remove();
  };

  @action
  selectPress = () => {
    this.itemData.isSelect = !this.itemData.isSelect;
    let money = this.itemData.money * this.itemData.count;
    if (this.itemData.isSelect) {
      this.props.data.increase(money);
    }
    else {
      this.props.data.reduce(money)
    }
    this.props.data.itemPress();
  };

  @action
  increase = () => {
    this.itemData.count += 1;
    if (this.itemData.isSelect) {
      this.props.data.increase(this.itemData.money);
    }else{
      this.itemData.isSelect = !this.itemData.isSelect;
      this.props.data.increase(this.itemData.money * this.itemData.count);
    }

  };

  @action
  reduce = () => {
    if (this.itemData.count <= 1) {
      if(this.itemData.isSelect){
        this.itemData.isSelect = !this.itemData.isSelect;
        this.props.data.reduce(this.itemData.money);
      }
      return;
    }
    this.itemData.count -= 1;
    if (this.itemData.isSelect) {
      this.props.data.reduce(this.itemData.money);
    }
  };

  render() {
    return (
      <View style={ styles.container }>
        <TouchableOpacity
          style={{ marginLeft : 15 }}
          onPress={ this.selectPress }>
          <Image source={ this.itemData.isSelect ?
            require('../imgs/login_radio_selected.png')
            : require('../imgs/login_radio_normall.png') }/>
        </TouchableOpacity>
        <Image style={ styles.icon } source={{ uri : 'https://img10.360buyimg.com/n7/jfs/t4063/153/323373745/444727/87c24f22/58b11156N9be178c2.jpg' }}/>
        <View style={ styles.right }>
          <Text style={ styles.nameStyle } numberOfLines={ 2 }>{ this.itemData.name }</Text>
          <Text style={ styles.descriptionStyle } numberOfLines={1}> { this.itemData.description }</Text>
          <View style={ styles.right_bot}>
            < Text style={ styles.moneyStyle }>¥{ this.itemData.money }</Text>
            <View style={ styles.numControllStyle }>
              <TouchableOpacity style={ styles.reduceStyle } onPress={ this.reduce }>
                <Text style={{ color : this.itemData.count <= 1 ? 'red' : 'black' } }>-</Text>
              </TouchableOpacity>
              <View style={ styles.numberViewStyle }>
                <Text style={ styles.numberStyle }>{ this.itemData.count }</Text>
              </View>
              <TouchableOpacity style={ styles.increaseStyle } onPress={ this.increase }>
                <Text>+</Text>
              </TouchableOpacity>
            </View>
          </View>
        </View>
      </View>
    );
  }
};

3-:MobxStore.js

import { observable, action, computed, autorun } from 'mobx';

export default class MobxStore {
  @observable
  itemData = {}

  //设置数据
  replace = (data) => {
    this.itemData = data;
  }

  //按下的反选
  itemPress = () => {
    let i = 0;
    this.itemData.datas.map((item) => {
      if (item.isSelect != true) {
        i += 1;
      }
    });
    if (i == 0) {
      this.itemData.isAllSelect = true;
    }
    else {
      this.itemData.isAllSelect = false;
    }
  }

  //加
  increase = (money) => {
    this.itemData.totalMoney += money;
  }

  //减
  reduce = (money) => {
    this.itemData.totalMoney -= money;
  }

  //全选
  selectAll = () => {
    this.itemData.isAllSelect = !this.itemData.isAllSelect;
    this.itemData.totalMoney = 0;
    if (this.itemData.isAllSelect) {
      for (let i = 0;
        i < this.itemData.datas.length;
        i++) {
        this.itemData.totalMoney += this.itemData.datas[ i ].money * this.itemData.datas[ i ].count;
      }
    }
  }
}

四:

1-:代码github地址:https://github.com/erhutime/React-Navigation-All/tree/master/All/jscode/shoppingcar/src

2-:下载完成后,修改index.ios.js:入口文件如下:

运行效果如下:

import App from './jscode/shoppingcar/src/App'
AppRegistry.registerComponent('All', () => App);

React-Native使用Mobx实现购物车功能

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 对象定义方法 简单易学
Mar 22 Javascript
JavaScript 放大镜 移动镜片效果代码
May 09 Javascript
javascript进行数组追加方法小结
Jun 16 Javascript
pace.js页面加载进度条插件
Sep 29 Javascript
BootStrap 智能表单实战系列(十)自动完成组件的支持
Jun 13 Javascript
js改变style样式和css样式的简单实例
Jun 28 Javascript
jQuery插件Easyui设置datagrid的pageNumber导致两次请求问题的解决方法
Aug 06 Javascript
Vue2.0用 watch 观察 prop 变化(不触发)
Sep 08 Javascript
vue-cli开发环境实现跨域请求的方法
Apr 07 Javascript
用npm安装vue和vue-cli,并使用webpack创建项目的方法
Sep 28 Javascript
vue实现给div绑定keyup的enter事件
Jul 31 Javascript
Vue表单提交点击事件只允许点击一次的实例
Oct 23 Javascript
JavaScript requestAnimationFrame动画详解
Sep 14 #Javascript
SVG动画vivus.js库使用小结(实例代码)
Sep 14 #Javascript
浅谈AngularJS中使用$resource(已更新)
Sep 14 #Javascript
jQuery plugin animsition使用小结
Sep 14 #jQuery
angular.extend方法的具体使用
Sep 14 #Javascript
浅谈angular.copy() 深拷贝
Sep 14 #Javascript
说说AngularJS中的$parse和$eval的用法
Sep 14 #Javascript
You might like
弄了个检测传输的参数是否为数字的Function
2006/12/06 PHP
手把手教你使用DedeCms V3的在线采集图文教程
2007/04/03 PHP
有关PHP中MVC的开发经验分享
2012/05/17 PHP
老生常谈PHP中的数据结构:DS扩展
2017/07/17 PHP
PHP7基于curl实现的上传图片功能
2018/05/11 PHP
php设计模式之职责链模式定义与用法经典示例
2019/09/19 PHP
改版了网上的一个js操作userdata
2007/04/27 Javascript
jcarousellite.js 基于Jquery的图片无缝滚动插件
2010/12/30 Javascript
js作用域及作用域链概念理解及使用
2013/04/15 Javascript
jQuery中bind与live的用法及区别小结
2014/01/27 Javascript
解决jQuery uploadify在非IE核心浏览器下无法上传
2015/08/05 Javascript
JS中的hasOwnProperty()和isPrototypeOf()属性实例详解
2016/08/11 Javascript
jQuery progressbar通过Ajax请求实现后台进度实时功能
2016/10/11 Javascript
简单理解vue中实例属性vm.$els
2016/12/01 Javascript
js实现简单的手风琴效果
2017/02/27 Javascript
JS中关于正则的巧妙操作
2017/08/31 Javascript
详解http访问解析流程原理
2017/10/18 Javascript
vue项目中定义全局变量、函数的几种方法
2019/11/08 Javascript
微信小程序实现下滑到底部自动翻页功能
2020/03/07 Javascript
TensorFlow实现Batch Normalization
2018/03/08 Python
更改Python的pip install 默认安装依赖路径方法详解
2018/10/27 Python
python批量下载网站马拉松照片的完整步骤
2018/12/05 Python
Python自定义函数计算给定日期是该年第几天的方法示例
2019/05/30 Python
python代码实现逻辑回归logistic原理
2019/08/07 Python
.dcm格式文件软件读取及python处理详解
2020/01/16 Python
Python操作Excel工作簿的示例代码(\*.xlsx)
2020/03/23 Python
Python基于pandas爬取网页表格数据
2020/05/11 Python
HTML5之WebGL 3D概述(下)—借助类库开发及框架介绍
2013/01/31 HTML / CSS
一个不错的HTML5 Canvas多层点击事件监听实例
2014/04/29 HTML / CSS
测绘工程个人的自我评价
2013/11/10 职场文书
会计助理岗位职责
2014/02/17 职场文书
2014党员自我评议表范文
2014/09/20 职场文书
打架赔偿协议书范本
2014/10/26 职场文书
2014年工人工作总结
2014/11/25 职场文书
如何书写邀请函?
2019/06/24 职场文书
JavaScript实现简单的音乐播放器
2022/08/14 Javascript