|
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.checked = all , 把全选框的状态(true/false)直接赋值给所有的list.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.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.checked=== true){
sum += list.newprice *list.count
count += list.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.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.checked=== true){
sum += list.newprice *list.count
count += list.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;
}
}
}
来源:https://www.cnblogs.com/rabbit-lin0903/p/11603084.html |