RN的购物车实现( 数量,单价,总价,总数 )

1. 导入 JSON 数据: (data.json)

[
  {
    "id": "1",
    "image": "a",
    "money": "39",
    "name": "\u5fb7\u56fdOETTINGER\u5965\u4e01\u683c\u5927\u9ea6\u5564\u9152500ml*4\u7f50\/\u7ec4"
  },
  {
    "id": "2",
    "image": "b",
    "money": "40",
    "name": "\u5fb7\u62c9\u514b\uff08Durlacher\uff09 \u9ed1\u5564\u9152 330ml*6\u542c"
  },
  {
    "id": "3",
    "image": "c",
    "money": "109",
    "name": "\u5965\u5854\u5229\u91d1\u7235 \u5564\u9152500ml*12 \u5308\u7259\u5229\u539f\u88c5\u4f4e\u5ea6\u8fdb\u53e3\u5564\u9152\u9152\u6c34\u996e\u54c1"
  },
  {
    "id": "4",
    "image": "d",
    "money": "158",
    "name": "\u5fb7\u56fd\u5564\u9152 \u539f\u88c5\u8fdb\u53e3\u5564\u9152 flensburger\/\u5f17\u4f26\u65af\u5821\u5564\u9152 \u571f\u8c6a\u91d1\u5564 5L \u6876\u88c5\u5564\u9152"
  },
  {
    "id": "5",
    "image": "e",
    "money": "66",
    "name": "\u9752\u5c9b\u5564\u9152 \u7ecf\u5178 \u9187\u539a \u5564\u9152500ml*12\u542c\/\u7bb1 \u56fd\u4ea7 \u6574\u7bb1"
  },
  {
    "id": "6",
    "image": "f",
    "money": "140",
    "name": "\u4eac\u59ff \u767e\u5a01\u7f50\u88c5330ml*24 \u5564\u9152"
  },
  {
    "id": "7",
    "image": "g",
    "money": "58",
    "name": "\u5fb7\u56fdOETTINGER\u5965\u4e01\u683c\u81ea\u7136\u6d51\u6d4a\u578b\u5c0f\u9ea6\u5564\u9152500ml*4\u7f50\/\u7ec4"
  },
  {
    "id": "8",
    "image": "h",
    "money": "695",
    "name": "Martell\u9a6c\u7239\u5229\u540d\u58eb1000ML \u8fdb\u53e3\u6d0b\u9152 \u540d\u4ed5\u5e72\u9091\u767d\u5170\u57301L"
  },
  {
    "id": "9",
    "image": "i",
    "money": "108",
    "name": "\u5965\u7f8e\u52a0\u94f6\u9f99\u820c\u5170\u3010OLMECA TEQUILA\u301138% 750ml"
  },
  {
    "id": "10",
    "image": "j",
    "money": "1386",
    "name": "\u4eba\u5934\u9a6c\u5929\u9187XO\u7279\u4f18\u9999\u69df\u5e72\u9091\u767d\u5170\u5730700ml"
  },
  {
    "id": "11",
    "image": "k",
    "money": "1080",
    "name": "40\u00b0\u6cd5\u56fd\u9a6c\u7239\u5229\u84dd\u5e26\u5e72\u9091\u767d\u5170\u5730700ml"
  },
  {
    "id": "12",
    "image": "l",
    "money": "598",
    "name": "\u6c99\u7687\u4f0f\u7279\u52a0\u585e\u73de700ml\u9650\u91cf\u7248"
  },
  {
    "id": "13",
    "image": "m",
    "money": "92",
    "name": "\u767e\u52a0\u5f97\u9ed1\u6717\u59c6\u9152 \u70c8\u9152 750ml"
  },
  {
    "id": "14",
    "image": "n",
    "money": "99",
    "name": "Seagrams Gin 750ML 40\u5ea6"
  },
  {
    "id": "15",
    "image": "o",
    "money": "1060",
    "name": "\u9a6c\u7239\u5229\u84dd\u5e26\u5e72\u9091\u767d\u5170\u5730 700ml"
  },
  {
    "id": "16",
    "image": "p",
    "money": "158",
    "name": "\u5f20\u88d5\u89e3\u767e\u7eb3\u5e72\u7ea2\u8461\u8404\u9152\u53cc\u652f\u793c\u76d2 750ml*2"
  },
  {
    "id": "17",
    "image": "q",
    "money": "1230",
    "name": "\u7231\u4e4b\u6e7e+\u5170\u8d35\u4eba\u7ec4\u5408"
  },
  {
    "id": "18",
    "image": "r",
    "money": "138",
    "name": "\u83f2\u5361\u73cd\u85cf\u838e\u5f53\u59ae\u8461\u8404\u9152750ml"
  },
  {
    "id": "19",
    "image": "s",
    "money": "1580",
    "name": "\u62c9\u56fe\u5609\u5229\u5e84\u56ed\u5e72\u7ea2\u8461\u8404\u9152"
  },
  {
    "id": "20",
    "image": "t",
    "money": "1890",
    "name": "\u62a5\u6069\u57ce\u5821\u5e72\u7ea2\u8461\u8404\u9152 \u516d\u652f\u88c5"
  },
  {
    "id": "21",
    "image": "x",
    "money": "2360",
    "name": "\u8c6a\u514b\u739b\u6b4c\u5e84\u56ed\u5e72\u7ea2\u8461\u8404\u9152 750ml 1\u652f\u88c5"
  },
  {
    "id": "22",
    "image": "y",
    "money": "98",
    "name": "\u767d\u6d6a\u838e\u5e84\u56ed\u5e72\u7ea2\u8461\u8404\u9152 750ml"
  }
]

2. 设置底部的总计 View ( XZHBottomView.js )


import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    TouchableOpacity,
    Image,
    ScrollView,
    DeviceEventEmitter
} from 'react-native';

var Dimensions = require('Dimensions');
var {width, height} = Dimensions.get('window');

class XZHBottomView extends Component{
    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            // 购买商品总金额
            totalPrice: 0,
            // 购买的酒数组
            buyWineArr: []
        };
    }


    render(){
        return(
            <View style={styles.viewStyle}>
                <View style={styles.leftView}>
                    <Text style={{fontSize:18}}>总价:</Text>
                    <Text style={{fontSize:18, color:'red'}}>¥{this.state.totalPrice}</Text>
                </View>
                <View style={styles.rightView}>
                  <TouchableOpacity onPress={()=>this._buy()}>
                    <Text style={{fontSize:16, marginRight:5}}>购买</Text>
                  </TouchableOpacity>
                  <TouchableOpacity onPress={()=>this._clearGoods()}>
                    <Text style={{fontSize:16, color:'red'}}>清空购物车</Text>
                  </TouchableOpacity>
                </View>
            </View>
        )
    }


    /**
     * 点击购买
     * @private
     */
    _buy() {
        var buyString = '您购买的商品清单: \n';
        this.state.buyWineArr.forEach((value, index)=>{
            buyString += '(' + (index+1) + ') 商品ID:' + value.id + ', 单价:' + value.money + ', 购买数量' + value.buyNum + '\n';
        });
        alert(buyString + '\n' + '总价:' + this.state.totalPrice + '元');
    }


    /**
     * 清空购物车
     * @private
     */
    _clearGoods() {
        // 1. 删除购物车中所有商品
        const buyWineArr = this.state.buyWineArr;
        buyWineArr.splice(0, buyWineArr.length);

        // 2. 更新状态,刷新UI
        this.setState({
            buyWineArr: buyWineArr,
            totalPrice: 0
        })

        // 3. 通知界面刷新
        DeviceEventEmitter.emit('refreshList', null);
    }


    componentDidMount() {
        this.notice = DeviceEventEmitter.addListener('changeTotalPrice', (wine)=>{
            // 1. 深拷贝一个新对象
            var tempWine = JSON.parse(JSON.stringify(wine));

            // 2. 判断
            var tempWineArr = this.state.buyWineArr;

            tempWineArr.forEach((value, index)=>{
                if(value.id == tempWine.id){
                    tempWineArr.splice(index, 1);
                }
            });

            if(tempWine.buyNum > 0){
                tempWineArr.push(tempWine);
            }

            // 3. 计算总价
            var totalPrice = 0;
            tempWineArr.forEach((value, index)=>{
                totalPrice += value.buyNum * value.money
            });

            // 4. 更新状态,刷新UI
            this.setState({
                totalPrice: totalPrice,
                buyWineArr: tempWineArr
            })
        });
    }

    componentWillUnMount() {
        this.notice.remove();
    }
}


const styles = StyleSheet.create({
    viewStyle:{

        flexDirection: 'row',
        height:44,
        borderTopWidth:1,
        borderTopColor:'#999',
        justifyContent:'space-between',
        alignItems:'center',
        backgroundColor:'#ccc',

        position:'absolute',
        bottom: 50,
        width: width
    },

    leftView:{
        flexDirection:'row',
        marginLeft: 8
    },

    rightView:{
        flexDirection:'row',
        marginRight: 8
    }
});


module.exports = XZHBottomView;

3.cellView 的布局 ( XZHWineCell.js )


import React, { Component, PropTypes } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    TouchableOpacity,
    Image,
    ScrollView,
    InteractionManager,
    DeviceEventEmitter
} from 'react-native';

var Dimensions = require('Dimensions');
var {width, height} = Dimensions.get('window');

class XZHWineCell extends Component{
    // 构造
      constructor(props) {
        super(props);

        // 初始状态
        this.state = {
            wine: this.props.wine
        };
      }

    render(){
        var wine = this.state.wine;
        return(
           <TouchableOpacity style={styles.viewStyle}>
               {/*左边*/}
               <TouchableOpacity style={styles.leftView}>
                    <Image source={{uri: wine.image}} style={styles.leftImageStyle}/>
                    <View style={{width:width * 0.7}}>
                        <Text
                            style={styles.titleStyle}
                            numberOfLines={1}
                        >
                            {wine.name}
                        </Text>
                        <Text>¥{wine.money}</Text>
                    </View>
               </TouchableOpacity>
               {/*右边*/}
               <View style={styles.rightView}>
                   <TouchableOpacity onPress={()=>this._removeWine(wine)}>
                       <Text style={[{fontSize:20}, styles.circleStyle]}>-</Text>
                   </TouchableOpacity>
                   <Text style={{fontSize:20, margin: 10}}>{wine.buyNum}</Text>
                   <TouchableOpacity  onPress={()=>this._addWine(wine)}>
                       <Text style={[{fontSize:20}, styles.circleStyle]}>+</Text>
                   </TouchableOpacity>
               </View>
           </TouchableOpacity>
        )
    }


    componentWillUpdate(nextProps) {
         // 接收通知
         this.notice = DeviceEventEmitter.addListener('refreshList', ()=>{
             // 1. 购买数量清零
             const tempWine = this.state.wine;
             tempWine.buyNum = 0;

             this.setState({
                 wine: tempWine
             })
         });
    }


    componentDidUnMount() {
        // 移除通知
        this.notice.remove();
    }

    /**
     * 移除商品
     */
    _removeWine(wine){
        // 1.判断
        if(wine.buyNum == 0){
            alert('商品数量不能小于0');
            return;
        }

        // 2. 改变数量
        wine.buyNum --;
        this.setState({
            wine: wine
        });

        // 3. 发出通知
        this._changeTotalPrice(wine);
    }

    /**
     * 添加商品
     */
    _addWine(wine){
        // 1. 改变数量
        wine.buyNum ++;
        this.setState({
            wine: wine
        });

        // 2. 发出通知
        this._changeTotalPrice(wine);
    }


    /**
     * 发出通知
     * @param wine 购买的商品
     * @private
     */
    _changeTotalPrice(wine){
        DeviceEventEmitter.emit('changeTotalPrice', wine);
    }

}

const styles = StyleSheet.create({
    viewStyle:{
        flexDirection:'row',
        backgroundColor:'#fff',
        borderBottomWidth:1,
        borderBottomColor: '#ccc'
    },

    leftView:{
        width: width * 0.7,
        flexDirection:'row',
        overflow:'hidden',
        alignItems:'center'
    },

    leftImageStyle: {
        width: 60,
        height: 60,
        margin: 5
    },

    rightView: {
        width: width * 0.3,
        flexDirection: 'row',
        justifyContent:'center',
        alignItems:'center'
    },

    titleStyle:{
        width: 0.5 * width
    },

    circleStyle:{
        width: 30,
        height: 30,
        borderRadius: 15,
        borderWidth:1,
        borderColor:'red',
        textAlign:'center',
        alignItems:'center',
        color:'blue',
        fontWeight:'900'
    }
});


module.exports = XZHWineCell;

4. 购物车页面 ( XZHMain.js )

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */


/*
* 案例博客 :  http://yiweifen.com/html/news/WaiYu/105343.html
* */

import React, {Component} from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    ListView,
    DeviceEventEmitter
} from 'react-native';

import XZHBottomView from './XZHBottomView';
import XZHWineCell from  './XZHWineCell';

var data = require('./data.json');

export default class extends Component {
    // 构造
    constructor(props) {
        super(props);

        // 创建数据源
        var ds = new ListView.DataSource({
            rowHasChanged: (r1, r2) => r1 !== r2
        });

        // 初始状态
        this.state = {
            dataArr: data,
            dataSource: ds
        };
    }

    render() {
        return (
            <View style={styles.container}>
                <ListView
                    dataSource={this.state.dataSource}
                    renderRow={(rowData)=> this._renderRow(rowData)}
                    contentInset={{bottom: 44}}
                />
                <XZHBottomView style={styles.bottomViewStyle}/>
            </View>
        );
    }

    _renderRow(rowData){
        return(
            <XZHWineCell wine={rowData} />
        )
    };

    componentWillMount() {
        for (var i = 0; i < data.length; i++) {
            // 1. 取出单个对象
            var item = data[i];
            // 2. 定义购买数量 并 插入对象
            item.buyNum = 0;
        }

        this.setState({
            dataSource: this.state.dataSource.cloneWithRows(this.state.dataArr)
        });
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#e8e8e8',
    },

    bottomViewStyle: {}
});

5. 引入 XAHMain.js 使用即可



在 React Native 中实现数据表格的思路与在普通的 Web 应用中类似,都是需要使用数据渲染表格。下面是一个简单的实现步骤: 1. 通过请求获取需要展示的数据,将数据存储在状态变量中。 2. 根据数据渲染表格的头部,可以使用 `View` 和 `Text` 组件实现。 3. 根据数据渲染表格的内容。可以使用数组的 `map` 方法遍历数据,使用 `View` 和 `Text` 组件来展示每一行数据。 4. 可以对表格的头部和内容进行样式的调整,例如设置表格的宽度、字体大小和颜色等。 下面是一个简单的代码示例,实现了一个包含表格头部和内容的数据表格: ```jsx import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet } from 'react-native'; function DataTable() { const [data, setData] = useState([]); useEffect(() => { // 发送请求获取数据 fetch('https://example.com/data') .then(response => response.json()) .then(data => setData(data)) .catch(error => console.error(error)); }, []); return ( <View style={styles.table}> <View style={styles.header}> <Text style={styles.headerText}>Name</Text> <Text style={styles.headerText}>Age</Text> <Text style={styles.headerText}>Gender</Text> </View> {data.map(item => ( <View style={styles.row} key={item.id}> <Text style={styles.text}>{item.name}</Text> <Text style={styles.text}>{item.age}</Text> <Text style={styles.text}>{item.gender}</Text> </View> ))} </View> ); } const styles = StyleSheet.create({ table: { borderWidth: 1, borderColor: '#ccc', margin: 10, }, header: { flexDirection: 'row', backgroundColor: '#eee', padding: 10, }, headerText: { fontWeight: 'bold', flex: 1, textAlign: 'center', }, row: { flexDirection: 'row', borderBottomWidth: 1, borderBottomColor: '#ccc', padding: 10, }, text: { flex: 1, textAlign: 'center', }, }); ``` 在这个代码示例中,我们通过 `fetch` 发送请求获取数据,并将数据存储在状态变量 `data` 中。在组件的返回值中,我们先展示了表格的头部,使用 `View` 和 `Text` 组件实现。然后我们使用数组的 `map` 方法遍历数据,使用 `View` 和 `Text` 组件来展示每一行数据。我们还对表格的头部和内容进行了样式的调整,例如设置了表格的宽度、字体大小和颜色等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小毅哥哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值