React == 實現簡易版購物車
1、幾個要點:
為了方便后面使用input type = "checkbox" 實現復選框的選中/不選中,給傳遞過來的屬性要在遍歷的時候,單獨加上一個新屬性 checked
count 屬性 默認值 都是1.
state = {
all : false, sumprice :0, one : false, sumcount:0
}
state對象 :
- all -----> 用來定義全選按鈕
- sumprice -----> 用來定義總價
- one -----> 用來控制 結算按鈕的樣式(當選中的其中任何一條購物車條目時候,顯示橘色,當沒有任何一條選中,顯示灰色)
- sumcount ----> 用來顯示購物車的總數量,顯示在頁面中
2、單選框的實現
1)首先是渲染的都是同樣的樣式,所以在這里傳遞一個index特別關鍵,通過index的傳遞才能夠知道操作的是哪條
2)當onchange事件發生的時候,對當前checked屬性進行取反。list[index].checked = ! list[index].checked。
3)單選框決定全選框:使用了數組的every方法(只有數組的每一項都滿足條件,才會返回true),用所有datalist的單選框都是true的時候,全選按鈕才會為true
4)單選框的選中與否決定結算框的樣式:one : list[index].checked // 為true的時候,one : true
// 單選 handleChange(index){ var list = [...this.state.datalist] list[index].checked = !list[index].checked // every方法 var every=list.every((item,index)=>{ return item.checked==true; }) // 單選框中如果有一個是 checked的是true就可以 var some = list.some((item,index)=>{ return list[index].checked }) this.setState({ datalist :list, all : every, //全選按鈕,只有當所有的list[index]=== true 的時候才會返回true one : some //設定結算框的樣式是哪個,根據list[index].checked }) this.SumPrice() }
3、全選按鈕的實現
1)當點擊全選框,對全選框的狀態進行取反
2)點擊全選按鈕的時候,所有的單選框的為true / false 直接取決的 全選框按鈕當前的狀態true / false
遍歷所有的list[i].checked = all , 把全選框的狀態(true/false)直接賦值給所有的list[i].checked 。
3)當全選的時候,結算框的樣式直接會跟隨變動,當為false,即沒有一個購物車條目唄選中,此時結算框的狀態為灰色。當為true,結算框為橘色。
<input type="checkbox" onChange={()=>{this.handleAll()}} checked={this.state.all} value=""/> // 全選 handleAll(){ var list = [...this.state.datalist] var all = this.state.all all = ! all //onchange事件發生,就是對當前的狀態進行取反 for(var i = 0 ; i < list.length ;i++){ list[i].checked = all // 全選框的狀態直接影響所有的單選框,就把全選框的狀態賦給所有的單選框即可 } this.setState({ all : all, one : all //全選的狀態直接影響結算框的樣式 }) this.SumPrice() }
4、購物車數量加減的實現
1)數量增加Add
重要的還是傳遞對應的index,才能准確地知道操作的是哪個購物車條目
list[index].count++
2)數量減少Minus
還有進行一步判斷,當此時購物車的數量已經是1的時候,不允許再繼續減了
list[index].count--
list[index].count<1?1:list[index].count
<button className={style.minus} onClick={()=>{this.handleMinus(index)}}>-</button> <input type="text" value={this.state.datalist[index].count||''}/> <button className={style.add} onClick={()=>{this.handleAdd(index)}}>+</button> // 加 handleAdd(index){ // 設定的value= {this.state.datalist[index].count} var list = [...this.state.datalist] list[index].count++; this.setState({ datalist : list, }) this.SumPrice() } //減 handleMinus(index){ // 設定的value= {this.state.datalist[index].count} var list = [...this.state.datalist]; list[index].count-- list[index].count=list[index].count<1?1:list[index].count; this.setState({ datalist : list }) this.SumPrice() }
5、總價的實現
1)遍歷所有的datalist,只有當其中每一個checked屬性為true的時候(表明已經被勾選上了,此時可以計算),才去計算金額
2)得到所有的總價,還能得到當前選中的數量一共有多少
SumPrice(){ var sum=0 var count = 0; var list = [...this.state.datalist] for(var i =0; i< list.length ;i++){ if(list[i].checked=== true){ sum += list[i].newprice *list[i].count count += list[i].count } } this.setState({ sumprice : sum, sumcount : count //結算個數 }) }
6、當進行 數量 的增加、減少、單選按鈕、全選按鈕的時候 都要重新調用計算總價的函數。
=============================================================================
完整代碼:
JS >
class CartPage extends Component { state = { datalist:[ { "imgUrl":"https://wochu.oss-cn-hangzhou.aliyuncs.com/upload/c8db2f99-d79e-4c4a-97e8-3e95c67a3b2e.jpg", "name": "小青菜350g", "newprice" : "4.5", "oldprice" : "4.9", "checked" :false, "count" :1 }, { "imgUrl":"https://img.wochu.cn/upload/abbc6852-711f-4d09-8e61-216c13505ccd.jpg", "name": "洪湖漁家香辣大閘蟹500g", "newprice" : "15.9", "oldprice" : "39.9", "checked" :false, "count" :1 }, { "imgUrl":"https://wochu.oss-cn-hangzhou.aliyuncs.com/upload/c8db2f99-d79e-4c4a-97e8-3e95c67a3b2e.jpg", "name": "小青菜350g", "newprice" : "4.5", "oldprice" : "4.9", "checked" :false, "count" :1 }, ], all : false, sumprice :0, one : false, sumcount:0 } render() { return ( <div className={style.cartList}> <div className={style.cartListItem}> <ul className={style.shopList} ref="myul"> {/* 對應的每個購物車條目 */} { this.state.datalist.map((item,index)=> <li key={index}> <input type="checkbox" className={style.checkbtn+' '+style.UnChecked} ref="mytext" onChange={()=>{this.handleChange(index)}} checked={item.checked} value="" /> <div className={style.shopImg}> {/* 點擊圖片跳轉到頁面詳情 */} <div className={style.shopImgShow}> <img src={item.imgUrl} alt=""/> </div> </div> {/* 商品詳情 */} <div className={style.shopInfo}> <div className={style.shopTitle}>{item.name}</div> <div className={style.shopCoupen}></div> <div className={style.shopPrice}> <div className={style.price}> <span>¥{item.newprice}</span> <i>¥{item.oldprice}</i> </div> <div className={style.shopSelect}> <button className={style.minus} onClick={()=>{this.handleMinus(index)}}>-</button> <input type="text" value={this.state.datalist[index].count||''}/> <button className={style.add} onClick={()=>{this.handleAdd(index)}}>+</button> </div> </div> </div> </li> ) } </ul> </div> <div className={style.sum}> <input type="checkbox" onChange={()=>{this.handleAll()}} checked={this.state.all} value=""/> <div className={style.checkPrice}> {/* 合算 */} <div className={style.totalPrice}> <span className={style.allsum}>合計</span> <span>¥{this.state.sumprice}</span> </div> {/* 不含運費 */} <div className={style.fee}>(不含運費)</div> </div> {/* 結算按鈕 */} <div className={this.state.one?style.btnCheck:style.btnNoCheck}>結算 <span>({this.state.sumcount})</span> </div> </div> </div> ); } // 單選 handleChange(index){ var list = [...this.state.datalist] list[index].checked = !list[index].checked var every=list.every((item,index)=>{ return item.checked==true; }) // 單選框中如果有一個是 checked的是true就可以 var some = list.some((item,index)=>{ return list[index].checked }) this.setState({ datalist :list, all : every, one : some //設定結算框的樣式是哪個,根據list[index].checked }) this.SumPrice() } // 全選 handleAll(){ var list = [...this.state.datalist] var all = this.state.all all = ! all for(var i = 0 ; i < list.length ;i++){ list[i].checked = all } this.setState({ all : all, one : all //全選的狀態直接影響結算框的樣式 }) this.SumPrice() } handleAdd(index){ // 設定的value= {this.state.datalist[index].count} var list = [...this.state.datalist] list[index].count++; this.setState({ datalist : list, }) this.SumPrice() } handleMinus(index){ // 設定的value= {this.state.datalist[index].count} var list = [...this.state.datalist]; list[index].count-- list[index].count=list[index].count<1?1:list[index].count; this.setState({ datalist : list }) this.SumPrice() } SumPrice(){ var sum=0 var count = 0; var list = [...this.state.datalist] for(var i =0; i< list.length ;i++){ if(list[i].checked=== true){ sum += list[i].newprice *list[i].count count += list[i].count } } this.setState({ sumprice : sum, sumcount : count //結算個數 }) } } export default CartPage;
CSS >
.cartList{ background:#f4f5f7; width:100%; top:.99rem; .cartListItem{ width:100%; background:#fff; margin-bottom:.04rem; // 購物車列表 .shopList{ width:100%; // height:1.11rem; padding:0 .09rem; background:#fff; li{ width:100%; height:1.11rem; border-bottom: 1px solid #e6e6e6; background: #fff; // 選中按鈕 .checkbtn{ width:.17rem; height:1.11rem; float:left; } // 選中時候的類名 .UnChecked{ background:url("../../../image/cart-img/unselect.png") no-repeat; background-size:100% .25rem; } // 點擊圖片跳轉 .shopImg{ width:1.1rem; height:1.1rem; margin:0 .1rem; float:left; .shopImgShow{ width:1.1rem; height:1.1rem; img{ width:100%; } } } // 購物車商品詳情 .shopInfo{ width:2.08rem; height:1.1rem; padding:.1rem 0; float:left; .shopTitle{ width:100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; height:.3rem; font-size:.14rem; } .shopCoupen{ width:2.08rem; height:.12rem; margin:.1rem 0; } .shopPrice{ width:2.08rem; height:.25rem; //價格 .price{ width:1.08rem; height:.21rem; float:left; span{ font-size:.15rem; color:#f96d16; } i{ font-size:.13rem; color:#999; text-decoration: line-through; font-style:normal; } } // 按鈕 .shopSelect{ float:right; width:.775rem; height:.25rem; .minus{ float:left; width:.225rem; height:.25rem; border:0; } input{ float:left; width:.325rem; height:.25rem; text-align: center; border:0; } .add{ float:left; width:.225rem; height:.25rem; border:0; } } } } } } } // 合算 div.sum{ width:100%; height:.5rem; background:#fff; padding-left:.1rem; position:fixed; bottom:.5rem; left:0; input{ height:100%; float:left; } .checkPrice{ float:left; width:1.48rem; height:.41rem; line-height: .41rem; padding:.08rem 0; margin-left:.1rem; // 合計 .totalPrice{ float: left; width:.869rem; height:.36rem; line-height:.36rem; font-size:.16rem; color:#f96d16; .allsum{ font-size:.13rem; color:#333; } } // 不含運費 .fee{ float:left; width:.61rem; font-size:.13rem; color:#999; } } // 結算按鈕 .btnCheck{ width:1.15rem; height:.49rem; background:rgb(249, 109, 22); float:right; line-height: .49rem; font-size:.18rem; color:#fff; text-align: center; } .btnNoCheck{ width:1.15rem; height:.49rem; background:rgb(153, 153, 153); float:right; line-height: .49rem; font-size:.18rem; color:#fff; text-align: center; } } }