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 相关文章推荐
jQuery中的常用事件总结
Dec 27 Javascript
jQuery Autocomplete自动完成插件
Jul 17 Javascript
JS 实现导航栏悬停效果(续2)
Sep 24 Javascript
通过js为元素添加多项样式,浏览器全兼容写法
Aug 30 Javascript
jquery实现键盘左右翻页特效
Apr 30 Javascript
jQuery实现滚动鼠标放大缩小图片的方法(附demo源码下载)
Mar 05 Javascript
简单实现js点击展开二级菜单功能
May 16 Javascript
JavaScript该如何学习 怎样轻松学习JavaScript
Jun 12 Javascript
Angularjs实现下拉框联动的示例代码
Aug 22 Javascript
vue 实现复制内容到粘贴板clipboard的方法
Mar 17 Javascript
vue实现移动端悬浮窗效果
Dec 01 Javascript
你知道JavaScript Symbol类型怎么用吗
Jan 08 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
php制作unicode解码工具(unicode编码转换器)代码分享
2013/12/24 PHP
PHP修改session_id示例代码
2014/01/08 PHP
使用ltrace工具跟踪PHP库函数调用的方法
2016/04/25 PHP
深入分析PHP设计模式
2020/06/15 PHP
JavaScript是否可实现多线程  深入理解JavaScript定时机制
2009/12/22 Javascript
js获取TreeView控件选中节点的Text和Value值的方法
2012/11/24 Javascript
js模拟点击以提交表单为例兼容主流浏览器
2013/11/29 Javascript
JS文字球状放大效果代码分享
2015/08/19 Javascript
js实现网站最上边可关闭的浮动广告条代码
2015/09/04 Javascript
JS检测移动端横竖屏的代码
2016/05/30 Javascript
js实现小窗口拖拽效果
2016/12/03 Javascript
详解Vue 事件驱动和依赖追踪
2017/04/22 Javascript
详解vue slot插槽的使用方法
2017/06/13 Javascript
详解react-native WebView 返回处理(非回调方法可解决)
2018/02/27 Javascript
Vue.js中的组件系统
2019/05/30 Javascript
微信小程序如何利用getCurrentPages进行页面传值
2019/07/01 Javascript
JS实现拖动模糊框特效
2020/08/25 Javascript
[57:59]EG vs Secret 2018国际邀请赛淘汰赛BO3 第一场 8.22
2018/08/23 DOTA
[01:16:16]DOTA2-DPC中国联赛定级赛 RNG vs Phoenix BO3第二场 1月8日
2021/03/11 DOTA
Python中staticmethod和classmethod的作用与区别
2018/10/11 Python
python实现推箱子游戏
2020/03/25 Python
Python自定义一个异常类的方法
2019/06/27 Python
wxPython实现整点报时
2019/11/18 Python
tensorflow 动态获取 BatchSzie 的大小实例
2020/06/30 Python
anaconda安装pytorch1.7.1和torchvision0.8.2的方法(亲测可用)
2021/02/01 Python
英国版MAC彩妆品牌:Illamasqua
2018/04/18 全球购物
Bodum官网:咖啡和茶壶、玻璃器皿、厨房电器等
2018/08/01 全球购物
阿迪达斯希腊官方网上商店:adidas希腊
2019/04/06 全球购物
政法大学毕业生自荐信范文
2014/01/01 职场文书
小学一年级评语大全
2014/04/22 职场文书
初中学习计划书范文
2014/09/15 职场文书
酒店辞职书怎么写
2015/02/26 职场文书
退货证明模板
2015/06/23 职场文书
2016年端午节校园广播稿
2015/12/18 职场文书
Python time库的时间时钟处理
2021/05/02 Python
go语言使用Casbin实现角色的权限控制
2021/06/26 Golang