鍍金池/ 問答/HTML/ react 購物車實現(xiàn)部分商品結(jié)算

react 購物車實現(xiàn)部分商品結(jié)算

問題

  • 如何計算被選中商品的總價,當商品數(shù)量發(fā)生改變
    情景:當超過一個以上的商品被選中時可以監(jiān)聽到所有選中商品的價格,但是如果修改其中一個商品數(shù)量時,只監(jiān)聽到了被修改商品的信息。

圖片描述
修改數(shù)量前勾選都可以監(jiān)聽到
修改數(shù)量前勾選都可以監(jiān)聽到
圖片描述
只監(jiān)聽到修改的
圖片描述
我需要當check box 狀態(tài)改變時,total 數(shù)量發(fā)生相應(yīng)變換。如果一個選中的產(chǎn)品數(shù)量變化時total也發(fā)生相應(yīng)改變

結(jié)構(gòu)

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>

        )
    }
}
數(shù)據(jù)結(jié)構(gòu)
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
    },
];
回答
編輯回答
故人嘆

代碼太多,不看。
只說思路。
首先給個總價的state就叫price
要解決的幾個點,
第一左邊的點擊按鈕,

clipboard.png

// 判斷是否已經(jīng)被選中
if (select) {
    // 已經(jīng)被選中了,那么就this.state.price - 減去當前的總價格也就是右邊的框的價格
} else {
    // 否則price加上右邊的總價格
}

關(guān)于如何判斷是否選中,給父級或者當前的元素加個類名就可以了

第二商品數(shù)量點擊

clipboard.png

// 前面還是一樣,判斷是否已經(jīng)被選中,如果沒有被選中,那么用戶點擊之后下面的價格不變,只變右邊的總價格,如果沒有被選中,那么每點擊一下就獲取當前的點擊的商品的單件價格,點的是減那么price就減去這個單件價格,加price就加上這個單件價格

這種方式會使用很多dom方法(不過貌似操作dom的比較少)而且因為你的每一件商品都是直接用的組件所以要傳很多回調(diào),綜上,還是用redux吧。

2018年8月29日 01:54
編輯回答
愚念

代碼有點多,大概看了一下,說一下我的思路吧。
首先的你數(shù)據(jù)結(jié)構(gòu),每一項至少應(yīng)該有商品的id吧,再加上一個是否選中和當前數(shù)量

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

父組件維護兩個state,一個是包含被勾選商品的數(shù)組,另一個是總價(總價遍歷數(shù)組算出來就可以了)

對于子組件來說有兩個動作,勾選和改變數(shù)量,無論哪個動作發(fā)生都把當前這條數(shù)據(jù)傳給父組件
父組件拿到數(shù)據(jù)后遍歷被勾選商品的數(shù)組,對比id
1.如果沒有找到相同id,再看是否選中,沒有選中不做操作,選中了就加到數(shù)組里
2.有相同id,看是否選中,沒有選中就把這條從數(shù)組里去除,選中了的就更新商品數(shù)量
就是這樣~ 若可行望采納

2017年10月6日 19:50
編輯回答
憶往昔

設(shè)置總價為一個獨立組件,然后修改子項目的價格的時候改變store,return new state emit事件 總價就會更新了

2017年5月16日 04:56