兩種方法jquery, vue構(gòu)建購(gòu)物車

我用兩種方法構(gòu)建了購(gòu)物車頁(yè)面哮针,分別是jquery和vue。

1. 分析頁(yè)面邏輯

1.1 設(shè)計(jì)圖如下:

圖1:
image.png

圖2:
image.png

圖3:
image.png

可以整理出功能有這些:

  • 基礎(chǔ)的頁(yè)面渲染,將商品列表渲染到頁(yè)面上淤年,這步不贅述啦
  • 點(diǎn)擊商品條目中的+,-號(hào):商品【數(shù)量增減】蜡豹,(且注意數(shù)量不能減為0)麸粮,下端總價(jià)和總數(shù)實(shí)時(shí)更新
  • 點(diǎn)擊商品條目的input:* 商品【選中】,下端總價(jià)和總數(shù)實(shí)時(shí)更新镜廉,存儲(chǔ)選中的商品id弄诲;
    (若有商品被選中,右下按鈕變色娇唯,可被點(diǎn)擊)
  • 點(diǎn)擊頁(yè)面圖1右上角【編輯】:右下角的下單按鈕變成刪除齐遵,進(jìn)入編輯狀態(tài)
  • 點(diǎn)擊右下按鈕,【刪除】或【下單】:需設(shè)置狀態(tài)變量state塔插,判斷頁(yè)面是否處于編輯狀態(tài)梗摇,再調(diào)用相應(yīng)接口
1.2 終上所述,我們需要定義的全局變量有:
goods: [],               //暫存接口返回的商品列表想许,用于渲染頁(yè)面
state: 0,                 //0:商品選擇狀態(tài)伶授,1:編輯狀態(tài)
selectIds: [],           //被選中的商品id列表,用于傳給下單或刪除接口伸刃。
readyToOrder: 0,   //有選中的商品谎砾,可以下單
totPrice: 0.00,        //選中商品總價(jià)
totNum: 0              //選中商品總數(shù)

2. vue構(gòu)建方法

2.1 商品數(shù)量增減

這里用商品數(shù)量減少做例子,首先在html中用【v-on:click】(簡(jiǎn)寫成@click)屬性在-的div上綁定 minus()方法捧颅,并傳商品id進(jìn)函數(shù)景图。
如果對(duì)v-on事件處理不熟悉闊以點(diǎn)這里

         <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>

再來(lái)進(jìn)入js部分,我將minus方法的代碼分成前端后端兩部分碉哑。
前端部分即前端保存的商品列表中該商品數(shù)量的減少挚币,
后端部分即與后端交互,調(diào)用數(shù)量更新接口扣典,改動(dòng)數(shù)據(jù)庫(kù)中該用戶購(gòu)物車中該商品的數(shù)量妆毕。

        /*
         *商品數(shù)量減少
         */
        minus(id) {
          /* front-end */
          var num = 0;           //改后的數(shù)量
          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);
          });
        },

未完待續(xù)嗷嗷.................


2.2
2.3
2.4
2.x 完整的【購(gòu)物車組件】代碼
<template>
  <div id="purchasingShoppingCart">
    <header>
        <p>購(gòu)物車</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:選擇狀態(tài),1:編輯狀態(tài)
          selectIds: [],
          readyToOrder: 0, //有選中的商品贮尖,可以下單
          totPrice: 0.00,
          totNum: 0
        }
      },
      created () {
        /**
          *請(qǐng)求購(gòu)物車列表
          */
        var cartObject = {
          "buyerId": 1
        };
        this.$http.post('/shoppingCart/shoppingCartList', cartObject).then(res => {
          console.log(res);
          this.goods = res.data.shoppingCartList;
          // 為商品賦選中狀態(tài)初始值
          this.goods.forEach(function(element) {
            Vue.set(element,'selected',0);
          });
        }).catch(error => {
          console.log(error);
        });
      },
      methods: {
        /*
         *點(diǎn)擊購(gòu)物車條目跳轉(zhuǎn)至商品詳情
         */
        toDetail(id) {
          this.$router.push({
            path: "/storeDetail",
            query: {
              goodId: id
            }
          })
        },
        /**
          *選中一件商品
          */
        select(id) {
          var index = 0;
          /* 記錄該商品在goods中的下標(biāo)*/
          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;
          }
        },
        /*
         *商品數(shù)量減少
         */
        minus(id) {
          /* front-end */
          var num = 0;           //改后的數(shù)量
          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);
          });
        },
        /*
         *商品數(shù)量增加
         */
        add(id) {
          /* front-end */
          var num = 0;           //改后的數(shù)量
          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);
          });
        },
        /**
          *點(diǎn)擊編輯按鈕
          */
        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);
            });
          }
          /* 重新請(qǐng)求商品列表 */
          var cartObject = {
            "buyerId": 1
          };
          this.$http.post('/shoppingCart/shoppingCartList', cartObject).then(res => {
            console.log(res);
            this.goods = res.data.shoppingCartList;
            // 為商品賦選中狀態(tài)初始值
            this.goods.forEach(function(element) {
              Vue.set(element,'selected',0);
            });

            /*
            *局部刷新?
            *清空input的記錄笛粘,恢復(fù)到一切都不選中的狀態(tài)
            *總價(jià)總數(shù)恢復(fù)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上層,一直可見(jiàn)*/
    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構(gòu)建方法

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市薪前,隨后出現(xiàn)的幾起案子润努,更是在濱河造成了極大的恐慌,老刑警劉巖示括,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铺浇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡垛膝,警方通過(guò)查閱死者的電腦和手機(jī)鳍侣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吼拥,“玉大人倚聚,你說(shuō)我怎么就攤上這事∪幼铮” “怎么了秉沼?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)矿酵。 經(jīng)常有香客問(wèn)我唬复,道長(zhǎng),這世上最難降的妖魔是什么全肮? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任敞咧,我火速辦了婚禮,結(jié)果婚禮上辜腺,老公的妹妹穿的比我還像新娘休建。我一直安慰自己,他們只是感情好评疗,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布测砂。 她就那樣靜靜地躺著,像睡著了一般百匆。 火紅的嫁衣襯著肌膚如雪砌些。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天加匈,我揣著相機(jī)與錄音存璃,去河邊找鬼。 笑死雕拼,一個(gè)胖子當(dāng)著我的面吹牛纵东,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播啥寇,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼偎球,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼洒扎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起衰絮,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤逊笆,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后岂傲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡子檀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年镊掖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褂痰。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亩进,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缩歪,到底是詐尸還是另有隱情归薛,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布匪蝙,位于F島的核電站主籍,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏逛球。R本人自食惡果不足惜千元,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望颤绕。 院中可真熱鬧幸海,春花似錦、人聲如沸奥务。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)氯葬。三九已至挡篓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溢谤,已是汗流浹背瞻凤。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留世杀,地道東北人阀参。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瞻坝,于是被迫代替她去往敵國(guó)和親蛛壳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杏瞻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,156評(píng)論 25 707
  • 1、購(gòu)物車列表功能實(shí)現(xiàn) 點(diǎn)擊加入購(gòu)物車或者點(diǎn)擊購(gòu)物車圖標(biāo)后進(jìn)入購(gòu)物車頁(yè)面衙荐,在購(gòu)物車頁(yè)面中首先渲染cartList的...
    飛飛廉閱讀 3,943評(píng)論 0 1
  • 我有一個(gè)朋友忧吟,原來(lái)在職場(chǎng)上混得還不錯(cuò)砌函,后來(lái)當(dāng)上了經(jīng)理。半年后溜族,他遇到了一個(gè)問(wèn)題讹俊,就是他從來(lái)都不敢對(duì)員工大聲說(shuō)話,這...
    激烈過(guò)后閱讀 544評(píng)論 0 0
  • 為了忘記你煌抒,我曾遠(yuǎn)走他鄉(xiāng)仍劈。 最后一次回首向來(lái)處,你和他相對(duì)而立寡壮。 他是不是說(shuō)贩疙,看啊,那個(gè)人像條狗况既,你就笑了这溅。 于是...
    了兮兮閱讀 195評(píng)論 0 0
  • 過(guò)去三十多年,我一直覺(jué)得應(yīng)該做腳踏實(shí)地的掌握一門永遠(yuǎn)不會(huì)讓你餓肚子的技能才是最有安全感的事情坏挠。但是最近兩年芍躏,我意識(shí)...
    康康的秘密花園閱讀 240評(píng)論 0 0