react 购物车实现部分商品结算

问题

  • 如何计算被选中商品的总价,当商品数量发生改变
    情景:当超过一个以上的商品被选中时可以监听到所有选中商品的价格,但是如果修改其中一个商品数量时,只监听到了被修改商品的信息。

图片描述
修改数量前勾选都可以监听到
修改数量前勾选都可以监听到
图片描述
只监听到修改的
图片描述
我需要当check box 状态改变时,total 数量发生相应变换。如果一个选中的产品数量变化时total也发生相应改变

结构

ShopCart > CartRow

代码

parent component: ShopCart
class ShopCart extends Component{
    constructor(...args){
        super(...args);
        var that = this;
        this.state={
            isChecked: false,
            checkedCount: 0,
            total: 0
        };

        this.item = Constant.productCart;
        this.number = 0;

        this.countChecked = (isChecked) => {
            this.setState({isChecked: isChecked});
            
            isChecked ?
                this.setState({checkedCount: this.state.checkedCount + 1})
                :
                this.setState({checkedCount: this.state.checkedCount - 1})

        }

        this.totalCheckedPrice = (isChecked, totalPrice) => {

            if(isChecked) {
                console.log(totalPrice);
            }

        }


    }
    componentWillMount() {

    }
    componentDidMount(){


    }

    render(){
        return(
            <form  className="shopCart contain">

                <Table condensed hover>
                    <thead>
                        <tr>
                            <th className="hiddenColumn">
                                <label>
                                    <input type="checkbox" className="check-all check"/>
                                </label>
                            </th>
                            <th colSpan="2">Product</th>
                            <th>Price</th>
                            <th>Quantity</th>
                            <th>Total</th>
                            <th>Remove</th>
                        </tr>
                    </thead>
                    <tbody>
                    {
                        this.item.length > 0 &&
                            this.item.map((item, index) => {
                                return(
                                    <CartRow key={index}
                                             rowItem={item}
                                             countChecked = {this.countChecked}
                                             totalCheckedPrice = {this.totalCheckedPrice}
                                    />
                                )
                            })
                    }
                    </tbody>
                    <tfoot>
                        <tr>
                            <th></th>
                            <th></th>
                            <th>
                                <span className="orangeButton">
                                    Empty Cart
                                </span>
                            </th>
                            <th  colSpan="2">
                                Selected
                                <span className="orangeText">
                                     {this.state.checkedCount}
                                </span>
                                Items
                            </th>
                            <th>Total:
                                <span className="orangeText">
                                    {this.state.total}
                                </span>
                            </th>
                            <th className="checkout">
                                <span>
                                    Checkout
                                </span>
                            </th>
                        </tr>
                    </tfoot>

                </Table>
                
            </form >

        )
    }
}
child component: CartRow
class CartRow extends Component{
    constructor(...args){
        super(...args);
        var that = this;
        this.state={
            isChecked: false,
            count: 1,
        };

        //input(text) value changed control
        this.handleChange = (event) => {

            this.setState({count: event.target.value });
        }
        this.increment = () => {
            this.setState({count: this.state.count + 1});
        }
        this.decrement = () => {
            if(this.state.count > 1) {
                this.setState({count: this.state.count - 1});
            }
        }

        //input checkbox value changed control
        this.onChangedAction = (event) => {

            this.setState({isChecked: event.target.checked})

            event.target.checked ?
                this.props.countChecked(true)
                :
                this.props.countChecked(false)
        }

        //subTotal price when input(text) value changed
        this.subTotal = () => {

            this.props.totalCheckedPrice(this.state.isChecked, Math.abs(this.state.count * this.props.rowItem.price))

            return Math.abs(this.state.count * this.props.rowItem.price);
        }

    }
    componentWillMount() {

    }
    componentDidMount(){

    }

    render(){
        return(
             <tr>
                 <td className="hiddenColumn">
                    <input type="checkbox"
                           checked={this.state.isChecked}
                           onChange={this.onChangedAction.bind(this)}/>
                 </td>

                 <td className="hiddenColumn">
                    <img src={this.props.rowItem.image} alt=""/>
                 </td>

                 <td data-column="Product">
                     {this.props.rowItem.title}
                 </td>

                 <td data-column="Price">
                     {this.props.rowItem.price}
                 </td>

                 <td className="count" data-column="Quality">

                    <span className='fa-stack reduce'
                          onClick={this.decrement.bind(this)}>

                        <Fontawesome name="minus" stack='1x'></Fontawesome>
                    </span>

                    <input type="text" className="count-input"
                           onChange={this.handleChange.bind(this)}
                           value={this.state.count}/>

                    <span className='fa-stack add'
                          onClick={this.increment.bind(this)}>

                        <Fontawesome name="plus" stack='1x'></Fontawesome>
                    </span>

                 </td>

                 <td className="subTotal" data-column="SubTotal">
                    {
                        this.subTotal()
                    }
                 </td>

                 <td data-column="Remover">
                     <span className='fa-stack'>
                          <Fontawesome name="trash-o" stack='1x'></Fontawesome>
                      </span>

                 </td>
            </tr>

        )
    }
}
数据结构
exports.productCart= [
    {
        title: 'Hello my demo2',
        image: 'https://pbs.twimg.com/media/CwGgapPVUAA4u3Q.jpg',
        price:  76

    },
    {
        title: 'Hello my demo2',
        image: 'http://i.imgur.com/RRUe0Mo.png',
        price:  676

    },
    {
        title: 'Pasifika Early Childhood CD (with printed lyrics)',
        image: 'https://static.guim.co.uk/sys-images/Guardian/Pix/pictures/2014/4/11/1397210130748/Spring-Lamb.-Image-shot-2-011.jpg',
        price:  234

    },
    {
        title: 'Hello my demo2',
        image: 'http://mblogthumb1.phinf.naver.net/20121009_136/dogtalk__1349752474508pRuyE_JPEG/Puppy-Love-29817_large.jpg?type=w2',
        price:  788

    },
    {
        title: 'Hello my demo2',
        image: 'https://www.codeproject.com/KB/GDI-plus/ImageProcessing2/flip.jpg',
        price:  96

    },
    {
        title: 'Hello my demo2',
        image: 'https://amazingslider.com/wp-content/uploads/2012/12/dandelion.jpg',
        price:  67
    },
];
阅读 5.2k
3 个回答

代码有点多,大概看了一下,说一下我的思路吧。
首先的你数据结构,每一项至少应该有商品的id吧,再加上一个是否选中和当前数量

    {
        id: '1'
        title: 'Hello my demo2',
        image: 'https://pbs.twimg.com/media/CwGgapPVUAA4u3Q.jpg',
        price:  76,
        num: 2,
        checked: true
    }

父组件维护两个state,一个是包含被勾选商品的数组,另一个是总价(总价遍历数组算出来就可以了)

对于子组件来说有两个动作,勾选和改变数量,无论哪个动作发生都把当前这条数据传给父组件
父组件拿到数据后遍历被勾选商品的数组,对比id
1.如果没有找到相同id,再看是否选中,没有选中不做操作,选中了就加到数组里
2.有相同id,看是否选中,没有选中就把这条从数组里去除,选中了的就更新商品数量
就是这样~ 若可行望采纳

代码太多,不看。
只说思路。
首先给个总价的state就叫price
要解决的几个点,
第一左边的点击按钮,

clipboard.png

// 判断是否已经被选中
if (select) {
    // 已经被选中了,那么就this.state.price - 减去当前的总价格也就是右边的框的价格
} else {
    // 否则price加上右边的总价格
}

关于如何判断是否选中,给父级或者当前的元素加个类名就可以了

第二商品数量点击

clipboard.png

// 前面还是一样,判断是否已经被选中,如果没有被选中,那么用户点击之后下面的价格不变,只变右边的总价格,如果没有被选中,那么每点击一下就获取当前的点击的商品的单件价格,点的是减那么price就减去这个单件价格,加price就加上这个单件价格

这种方式会使用很多dom方法(不过貌似操作dom的比较少)而且因为你的每一件商品都是直接用的组件所以要传很多回调,综上,还是用redux吧。

设置总价为一个独立组件,然后修改子项目的价格的时候改变store,return new state emit事件 总价就会更新了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题