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
<input type="checkbox" className={style.checkbtn+' '+style.UnChecked} ref="mytext"
onChange={()=>{this.handleChange(index)}} checked={item.checked} value=""
/>
// 单选 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 ; } } }
查看更多关于React == 实现简易购物车的详细内容...