美文网首页我爱编程
两种方法jquery, vue构建购物车

两种方法jquery, vue构建购物车

作者: cirgh | 来源:发表于2018-06-07 16:56 被阅读0次

我用两种方法构建了购物车页面,分别是jquery和vue。

1. 分析页面逻辑

1.1 设计图如下:
图1: image.png 图2: image.png 图3: image.png

可以整理出功能有这些:

  • 基础的页面渲染,将商品列表渲染到页面上,这步不赘述啦
  • 点击商品条目中的+,-号:商品【数量增减】,(且注意数量不能减为0),下端总价和总数实时更新
  • 点击商品条目的input:* 商品【选中】,下端总价和总数实时更新,存储选中的商品id;
    (若有商品被选中,右下按钮变色,可被点击)
  • 点击页面图1右上角【编辑】:右下角的下单按钮变成删除,进入编辑状态
  • 点击右下按钮,【删除】或【下单】:需设置状态变量state,判断页面是否处于编辑状态,再调用相应接口
1.2 终上所述,我们需要定义的全局变量有:
goods: [],               //暂存接口返回的商品列表,用于渲染页面
state: 0,                 //0:商品选择状态,1:编辑状态
selectIds: [],           //被选中的商品id列表,用于传给下单或删除接口。
readyToOrder: 0,   //有选中的商品,可以下单
totPrice: 0.00,        //选中商品总价
totNum: 0              //选中商品总数

2. vue构建方法

2.1 商品数量增减

这里用商品数量减少做例子,首先在html中用【v-on:click】(简写成@click)属性在-的div上绑定 minus()方法,并传商品id进函数。
如果对v-on事件处理不熟悉阔以点这里

         <div class="good-num">
            <div class="add" @click="add(good.id)">+</div>
            <div class="num" goodId="">{{good.goodsNum}}</div>
            <div class="minus" @click="minus(good.id)">-</div>
          </div>

再来进入js部分,我将minus方法的代码分成前端后端两部分。
前端部分即前端保存的商品列表中该商品数量的减少,
后端部分即与后端交互,调用数量更新接口,改动数据库中该用户购物车中该商品的数量。

        /*
         *商品数量减少
         */
        minus(id) {
          /* front-end */
          var num = 0;           //改后的数量
          for(var i=0;i<this.goods.length;i++) {
            if(this.goods[i].id == id) {
              this.goods[i].goodsNum--;
              this.totNum--;
              this.totPrice -= this.goods[i].price;
              num = this.goods[i].goodsNum;
            }
          }
          /* back-end */
          var numObject = {
            id: id,
            goodsNum: num
          };
          this.$http.post('/shoppingCart/shoppingCartUpdate', numObject).then(res => {
            console.log(res);
          }).catch(error => {
            console.log(error);
          });
        },

未完待续嗷嗷.................


2.2
2.3
2.4
2.x 完整的【购物车组件】代码
<template>
  <div id="purchasingShoppingCart">
    <header>
        <p>购物车</p>
        <div v-if="this.state==0"
             class="edit"
             @click="edit()">编辑
        </div>
        <div v-else class="edit"
             @click="edit()">完成
        </div>
    </header>

    <ul class="good-list">
      <li v-for="(good,index) in goods" :key="index">
        <label class="ql-ipt">
          <input type="checkbox"
                 class="comman-ipt"
                 @click="select(good.id)"><i></i></input>
        </label>
        <a @click="toDetail(good.id)">
          <img class="good-img"
              v-bind:src="'http://120.78.133.190'+good.pic"></img>
          <div class="good-info">
            <p class="good-title">{{good.name}}</p>
            <p class="good-detail">{{good.description}}</p>
            <p class="good-price">¥{{good.price}}</p>
          </div>
        </a>
        <div class="good-num-container">
          <div class="good-num">
            <div class="add" @click="add(good.id)">+</div>
            <div class="num" goodId="">{{good.goodsNum}}</div>
            <div class="minus" @click="minus(good.id)">-</div>
          </div>
        </div>
      </li>
    </ul>

    <div class="bottom">
        <!--label class="ql-ipt final-input">
          <input type="checkbox" class="fin-ipt"><i></i></input>
        </label-->
        <p class="bottom-text">已选 ( <span class="bottom-span">{{totNum}}</span> )</p>
        <p class="tot-price">¥<span class="bottom-price">{{totPrice}}</span></p>
        <button v-if="this.state==0"
                class="sub-btn"
                v-bind:class="{ green: selectIds.length }"
                @click="subOrDel()">下单
        </button>
        <button v-else
                class="sub-btn"
                v-bind:class="{ green: selectIds.length }"
                @click="subOrDel()">删除所选
        </button>
    </div>
  </div>
</template>

<script>
import Vue from 'vue'
    export default {
      name: 'purchasingShoppingCart',
      data () {
        return {
          goods: [],
          state: 0,        //0:选择状态,1:编辑状态
          selectIds: [],
          readyToOrder: 0, //有选中的商品,可以下单
          totPrice: 0.00,
          totNum: 0
        }
      },
      created () {
        /**
          *请求购物车列表
          */
        var cartObject = {
          "buyerId": 1
        };
        this.$http.post('/shoppingCart/shoppingCartList', cartObject).then(res => {
          console.log(res);
          this.goods = res.data.shoppingCartList;
          // 为商品赋选中状态初始值
          this.goods.forEach(function(element) {
            Vue.set(element,'selected',0);
          });
        }).catch(error => {
          console.log(error);
        });
      },
      methods: {
        /*
         *点击购物车条目跳转至商品详情
         */
        toDetail(id) {
          this.$router.push({
            path: "/storeDetail",
            query: {
              goodId: id
            }
          })
        },
        /**
          *选中一件商品
          */
        select(id) {
          var index = 0;
          /* 记录该商品在goods中的下标*/
          for(var i=0;i<this.goods.length;i++) {
            if(this.goods[i].id == id) {
              index = i;
            }
          }
          /* 记录selectIds */
          if(this.goods[index].selected == 0) {
            this.selectIds.push(id);
            console.log(this.selectIds);
            this.goods[index].selected = 1;

            this.totNum += this.goods[index].goodsNum;
            this.totPrice += this.goods[index].goodsNum * this.goods[index].price;
          } else {
            var j = this.selectIds.indexOf(id);
            this.selectIds.splice(j, 1);
            console.log(this.selectIds);
            this.goods[index].selected = 0;

            this.totNum -= this.goods[index].goodsNum;
            this.totPrice -= this.goods[index].goodsNum * this.goods[index].price;
          }
        },
        /*
         *商品数量减少
         */
        minus(id) {
          /* front-end */
          var num = 0;           //改后的数量
          for(var i=0;i<this.goods.length;i++) {
            if(this.goods[i].id == id) {
              this.goods[i].goodsNum--;
              this.totNum--;
              this.totPrice -= this.goods[i].price;
              num = this.goods[i].goodsNum;
            }
          }
          /* back-end */
          var numObject = {
            id: id,
            goodsNum: num
          };
          this.$http.post('/shoppingCart/shoppingCartUpdate', numObject).then(res => {
            console.log(res);
          }).catch(error => {
            console.log(error);
          });
        },
        /*
         *商品数量增加
         */
        add(id) {
          /* front-end */
          var num = 0;           //改后的数量
          for(var i=0;i<this.goods.length;i++) {
            if(this.goods[i].id == id) {
              this.goods[i].goodsNum++;
              this.totNum++;
              this.totPrice += this.goods[i].price;
              num = this.goods[i].goodsNum;
            }
          }
          /* back-end */
          var numObject = {
            id: id,
            goodsNum: num
          };
          this.$http.post('/shoppingCart/shoppingCartUpdate', numObject).then(res => {
            console.log(res);
          }).catch(error => {
            console.log(error);
          });
        },
        /**
          *点击编辑按钮
          */
        edit() {
          /* 编辑/编辑完成 */
          if(this.state == 0) {
              this.state = 1;
          } else {
              this.state = 0;
          }
        },
        /**
          *底部按钮
          *删除或下单
          */
        subOrDel() {
          var sidObject ={
            ids: JSON.parse(JSON.stringify(this.selectIds).replace(/\"/g, ""))
          };
          if(this.state == 0) {
            this.$http.post('/shoppingCart/placeOrder', sidObject).then(res => {
              console.log(res);
              //下单商品暂存
              localStorage.setItem("goods",JSON.stringify(res.data.data));
              localStorage.setItem("price",this,totPrice);

            }).catch(error => {
              console.log(error);
            });
          } else {
            this.$http.post('/shoppingCart/shoppingCartRemove', sidObject).then(res => {
              console.log(res);
            }).catch(error => {
              console.log(error);
            });
          }
          /* 重新请求商品列表 */
          var cartObject = {
            "buyerId": 1
          };
          this.$http.post('/shoppingCart/shoppingCartList', cartObject).then(res => {
            console.log(res);
            this.goods = res.data.shoppingCartList;
            // 为商品赋选中状态初始值
            this.goods.forEach(function(element) {
              Vue.set(element,'selected',0);
            });

            /*
            *局部刷新?
            *清空input的记录,恢复到一切都不选中的状态
            *总价总数恢复0
            *
            */

            this.$router.push({
              path: "/purchasingOrder",
              query: {

              }
            })
          }).catch(error => {
            console.log(error);
          });
        }
      }
    }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#purchasingShoppingCart {
    background-color: #fafafa;
}
/* header */
header {
    height:0.74rem;
    width: 100%;
    color: #ffffff;
    position: fixed;
    top:0;
    font-size: 0.26rem;
    z-index: 2;  /*使fixed覆盖在absolute上层,一直可见*/
    background-color: #5f6d61;
}
header p {
    text-align: center;
    padding-top: 0.24rem;
}
.edit {
    position: absolute;
    right: 0;
    top: 0.24rem;
    right: 0.28rem;
}


/* 商品列表 */
.good-list {
    width: 100%;
    position: absolute;
    top: 0.74rem;
    background-color: #fafafa;
    margin-bottom: 1.74rem;
}
.good-list li {
    height: 1.96rem;
    width: 100%;
    background-color: #ffffff;
    border-bottom: 0.02rem solid #dddddd;
    margin-bottom: 0.12rem;
}
.good-img {
    box-sizing: border-box;
    height: 1.12rem;
    width: 1.26rem;
    position: absolute;
    left: 0.70rem;
    margin-top: 0.36rem;
    border: 0.02rem solid #dddddd;
}
.good-info {
    position: absolute;
    left: 2.22rem;
    margin-top: 0.36rem;
    width: 2.50rem;
    height: 1.12rem;
}
.good-title {
    font-size: 0.24rem;
    position: absolute;
    top: 0;
    margin-bottom: 0.14rem;
}
.good-detail{
    color: #cccccc;
    font-size: 0.16rem;
    position: absolute;
    top: 0.45rem;
}
.good-price {
    color: #e51a19;
    font-size: 0.16rem;
    position: absolute;
    bottom: 0;
}
.good-num-container {
    position: absolute;
    right: 0.44rem;
    margin-top: 0.36rem;
    width: 1.3rem;
    height: 1.12rem;
}
.good-num {
    box-sizing: border-box;
    width: 1.20rem;
    height:0.30rem;
    position: absolute;
    bottom: 0;
    margin-top: 1.22rem;
    border: 0.01rem solid #8e8561;
    text-align: center;
}
.add {
    position: absolute;
    right: 0;
    width: 0.36rem;
}
.add span {
    color: #8e8561;
    font-size: 0.28rem;
    position: absolute;
    bottom: -0.32rem;
    right:0.08rem;
    text-align: center;
}
.num {
    height:0.28rem;
    box-sizing: border-box;
    position: absolute;
    right: 0.36rem;
    border-left: 0.01rem solid #8e8561;
    border-right: 0.01rem solid #8e8561;
    width: 0.48rem;
}
.minus {
    position: absolute;
    right: 0.84rem;
    width: 0.36rem;
}
.minus span {
    color: #8e8561;
    font-size: 0.28rem;
    position: absolute;
    bottom: -0.32rem;
    right:0.10rem;
    text-align: center;
}

/* input */
.ql-ipt input[type='radio'] + i, input[type='checkbox'] + i {
    position: absolute;
    left: 0.18rem;
    margin-top: 0.72rem;
}
.ql-ipt input[type='radio']:checked + i,
input[type='checkbox']:checked + i {
    /* background-color: #8e8561;; */
    background-position: 0 0;
}
.final-input input[type='checkbox'] + i {
    margin-top: 0.38rem;
}

/* bottom part 即下单处 */
.bottom {
    height: 1.06rem;
    width: 100%;
    border-top: 0.02rem solid #dddddd;
    position: fixed;
    bottom: 0rem;
    background-color: #ffffff;
}
.bottom-text {
    position: absolute;
    left: 0.70rem;
    margin-top: 0.40rem;
    font-size: 0.26rem;
}
.bottom-text span {
    font-size: 0.26rem;
}
.tot-price {
    margin-top: 0.40rem;
    position: absolute;
    right: 2.00rem;
    color: #e51a19;
}
.sub-btn {
    width: 1.76rem;
    height: 1.06rem;
    background-color: #dee2de;  /*#8e8561*/
    border: none;
    position: absolute;
    right: 0;
    color: #ffffff;
    font-size: 0.24rem;
}
.green {
     background-color: #8e8561;
}


/* 字体大小 */
.cd-f1 {
    font-size: 0.32rem;         /* 32/640 */
}
.cd-f2 {
    font-size: 0.3rem;          /* 30/640 */
}
.cd-f3 {
    font-size: 0.28rem;         /* 28/640 */
}
.cd-f4 {
    font-size: 0.26rem;         /* 26/640 */
}
.cd-f5 {
    font-size: 0.24rem;         /* 24/640 */
}
.cd-f6 {
    font-size: 0.22rem;         /* 22/640 */
}
.cd-fmin {
    font-size: 0.20rem;
}

/* 颜色 */
.answer-right {
    background-color: #003814;
}
.answer-wrong {
    background-color: #570100;
}
.answer-no-choice {
    background-color: #929292;
}
.color-base {
    color: #bfa355;
}

/* button */
.ql-btn {
    display: block;
    width: 1.46rem;
    height: 0.44rem;
    line-height: 0.44rem;
    font-size: 0.24rem;
    margin-left: 0.4rem;
    text-align: center;
    border-radius: 0.04rem;
    /* border: 0.01rem solid #f2f2f2; */
    background-color: transparent;
    border: none;
    outline: none;
}
.ql-btn:focus {
    color: #adaaaa;
}
.ql-btn-default {
    color: #fff;
    border: none;
    /* background-color: #bfa355; */
    background-color: #564932;
}

/* radio & checkbox */
.ql-ipt input[type='radio'], .ql-ipt input[type='checkbox'] {
    position: absolute;
    left: -555em;
}
.ql-ipt input[type='radio'] + i, .ql-ipt input[type='checkbox'] + i {
    display: inline;
    float: left;
    width: 0.38rem;
    height: 0.38rem;
    background: url('../../assets/images/icon_input.png') no-repeat;
    background-size: auto 0.38rem;
    background-position: -0.39rem 0;
}
.ql-ipt input[type='radio']:checked + i,
.ql-ipt input[type='checkbox']:checked + i {
    /* background-color: #8e8561;; */
    background-position: 0 0;
}


</style>

3. jquery构建方法

相关文章

网友评论

    本文标题:两种方法jquery, vue构建购物车

    本文链接:https://www.haomeiwen.com/subject/chesjftx.html