vuejs手把手教你写一个完整的购物车实例代码


Posted in Javascript onJuly 06, 2017

由于我们公司是主营业务是海淘,所以每个项目都是类似淘宝天猫之类的商城,那么购物车就是一个重点开发功能模块。介于之前我都是用jq来写购物车的,这次就用vuejs来写一个购物车。下面我就从全选,数量控制器,运费,商品金额计算等方法来演示一下一个能用在实际场景的购物车是怎么做出来的以及记录一下这次用vuejs踩过的坑。

1.一层数据结构-全选

下面这段代码和vuejs官网里面checkbox绑定很像。不明白的可以直接上vuejs官网看看。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuejs-全选</title>
<style type="text/css">
* {
  padding: 0;
  margin: 0;
}
a {
  color: #333;
  text-decoration:none;
}
</style>
</head>
<body>
<label>
  <input type="checkbox" name="all" v-on:click="chooseAll" v-model="selectArr.length==goodsList.length" />
  <span>全选</span>
</label>
<div v-for="(index, item) in goodsList">
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
    <input type="checkbox" :value="index" v-model="selectArr" />
    商品名称:<span v-html="item.name"></span> |
    价格:<span v-html="item.price"></span>
  </a>
</div>
<label>
  <input type="checkbox" name="all" v-on:click="chooseAll" v-model="selectArr.length==goodsList.length" />
  <span>全选</span>
</label>
<script src="http://cdn.bootcss.com/vue/1.0.7/vue.js"></script>
<script>
var vue = new Vue({
  el : 'body',
  data : {
    goodsList : [
      {
        name : '山本汉方1',
        price : '19.00'
      },
      {
        name : '山本汉方2',
        price : '19.00'
      },
      {
        name : '山本汉方3',
        price : '19.00'
      },
      {
        name : '山本汉方4',
        price : '19.00'
      },
      {
        name : '山本汉方5',
        price : '19.00'
      },
    ],
    selectArr : []
  },
  ready : function() {},
  methods : {
    chooseAll : function(event) {
      var oThis = this;
      oThis.selectArr = [];
      if ( event.currentTarget.checked ) {
        oThis.goodsList.forEach(function(item , index) {
          oThis.selectArr.push(index);
        });
      }
      console.log(oThis.selectArr);
    }
  }
})
</script>
</body>
</html>

2.二层数据结构-全选

一层数据结构的购物车在现实中是很少看到的,比如我们最熟悉的淘宝购物车是按照店铺分的,那么必然是多层的数据结构。这次在写这个二层数据接口的全选,碰到一个很大的坑,一开始我是用了一层数据结构的数据,发现当对象数组里面的某个值改变了,视图竟然没有触发!,所以会造成下面所有的checkbox都被选中了,最上面的那个全选checkbox竟然还是没有被选中。感觉告诉我这是vuejs的坑,后来发现是js的坑。具体可以看这个。方法是百度到了,可是放我这里没有用(应该是版本问题)。于是我就改了数据结构。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuejs-全选</title>
<style type="text/css">
* {
  padding: 0;
  margin: 0;
}
a {
  color: #333;
  text-decoration:none;
}
.goods-item {
  display: block;
}
.store-item {
  margin-bottom: 20px;
}
</style>
</head>
<body>
<div v-for="(index1, item) in goodsObj" class="store-item">
  <p>
    <span v-html="item.name"></span>
    <label>
      <input type="checkbox" name="all" v-on:click="chooseShopGoods(index1)" v-model="item.checked" />
      <span>全选</span>
    </label>
  </p>
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" v-for="(index, data) in item.list" class="goods-item">
    <input type="checkbox" v-model="data.checked" v-on:click="choose(index1, index)" />
    商品名称:<span v-html="data.name"></span> |
    价格:<span v-html="data.price"></span>
  </a>
</div>
<label>
  <input type="checkbox" name="all" v-on:click="chooseAllGoods()" v-model="allChecked" />
  <span>全选</span>
</label>
<script src="http://cdn.bootcss.com/vue/1.0.7/vue.js"></script>
<script>
var goodsObj = [
  {
    name : '大胖的店',
    checked : false,
    list : [
      {
        name : '麻辣二胖',
        price : 23.00,
        realStock : 10,
        fare : 1.5,
        num : 1,
        checked : false,
      },

      {
        name : '香辣二胖',
        price : 21.00,
        realStock : 2,
        fare : 1.5,
        num : 2,
        checked : false,
      },

      {
        name : '红烧二胖',
        price : 88.00,
        realStock : 8,
        fare : 1.5,
        num : 4,
        checked : false,
      }
    ]
  },

  {
    name : '二胖的店',
    checked : false,
    list : [
      {
        name : '漂亮的裙子',
        price : 166.00,
        realStock : 10,
        fare : 2,
        num : 1,
        checked : false,
      },

      {
        name : '漂亮的短袖',
        price : 188.00,
        realStock : 2,
        fare : 1.5,
        num : 2,
        checked : false,
      },

      {
        name : '漂亮的鞋子',
        price : 299.00,
        realStock : 1,
        fare : 3,
        num : 1,
        checked : false,
      }
    ]
  },

  {
    name : '胖胖的店',
    checked : false,
    list : [
      {
        name : '福满多',
        price : 3.00,
        realStock : 10,
        fare : .5,
        num : 10,
        checked : false,
      },

      {
        name : '精品卫龙',
        price : 1.50,
        realStock : 2,
        fare : 2,
        num : 2,
        checked : false,
      },

      {
        name : '周长江',
        price : 2.50,
        realStock : 3,
        fare : 5,
        num : 2,
        checked : false,
      }
    ]
  },
];
var vue = new Vue({
  el : 'body',
  data : {
    goodsObj : goodsObj,
    allChecked : false
  },
  ready : function() {

  },
  methods : {
    // 全部商品全选
    chooseAllGoods : function() {
      var flag = true;
      if ( this.allChecked ) {
        flag = false;
      }
      for ( var i = 0, len = this.goodsObj.length; i < len; i++ ) {
        this.goodsObj[i]['checked'] = flag;
        var list = this.goodsObj[i]['list'];
        for ( var k = 0, len1 = list.length; k < len1; k++ ) {
          list[k]['checked'] = flag;
        }
      }
      this.allChecked = !this.allChecked;
    },

    // 每个店铺全选
    chooseShopGoods : function( index) {
      var list = this.goodsObj[index]['list'],
        len = list.length;
      if ( this.goodsObj[index]['checked'] ) {
        for (var i = 0; i < len; i++ ) {
          list[i]['checked'] = false;
        }
      } else {
        for (var i = 0; i < len; i++ ) {
          list[i]['checked'] = true;
        }
      }
      this.goodsObj[index]['checked'] = !this.goodsObj[index]['checked'];

      // 判断是否选择所有商品的全选
      this.isChooseAll();
    },

    // 单个选择
    choose : function( index1, index) {
      var list = this.goodsObj[index1]['list'],
        len = list.length;
      if ( list[index]['checked'] ) {
        this.goodsObj[index1]['checked'] = false;
        this.allChecked = false;
        list[index]['checked'] = !list[index]['checked'];
      } else {
        list[index]['checked'] = !list[index]['checked'];

        // 判断是否选择当前店铺的全选
        var flag = true;
        for (var i = 0; i < len; i++ ) {
          if ( list[i]['checked'] == false ) {
            flag = false;
            break;
          }
        }
        flag == true ? this.goodsObj[index1]['checked'] = true : this.goodsObj[index1]['checked'] = false;
      }

      // 判断是否选择所有商品的全选
      this.isChooseAll();
    },

    // 判断是否选择所有商品的全选
    isChooseAll : function() {
      var flag1 = true;
      for ( var i = 0, len = this.goodsObj.length; i < len; i++ ) {
        if ( this.goodsObj[i]['checked'] == false ) {
          flag1 = false;
          break;
        }
      }
      flag1 == true ? this.allChecked = true : this.allChecked = false;
    },

  }
})
</script>
</body>
</html>

3.一层数据结构-数量选择器

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuejs-数量选择器(1层数据结构)</title>
<style type="text/css">
*{
  padding:0;
  margin: 0;
  box-sizing: border-box;
  font-size: 16px;
}
.clearfix:after {
  content: ".";
  visibility: hidden;
  display: block;
  height: .1px;
  font-size: .1em;
  line-height: 0;
  clear: both;
}
.quantity-selector {
  margin-bottom: 20px;
  width: 8.571rem;
  line-height: 2.857rem;
  border: 1px solid #d1d6e4;
  border-radius: 3px;
}
.quantity-selector .reduce, 
.quantity-selector .add {
  float: left;
  width: 33.33%;
  border-right: 1px solid #d1d6e4;
  text-align: center;
  cursor: pointer;
}
.quantity-selector .number {
  float: left;
  width: 33.33%;
  height: 2.857rem;
  padding: .5rem 0;
  line-height: 1rem;
  border: none;
  text-align: center;
}
.quantity-selector .add {
  border-left: 1px solid #d1d6e4;
  border-right: none;
}
.quantity-selector .disable {
  color: #d2d2d2;
  cursor: default;
}
</style>
</head>
<body>

<div v-for="data in goodsList">
  <p>商品数量 :<span v-html="data.num"></span></p>
  <p>商品库存 :<span v-html="data.realStock"></span></p>
  <div class="quantity-selector clearfix">
    <span class="reduce" v-on:click="numChange($index, -1)" v-bind:class="{ 'disable' : data.num==1 }">-</span>
    <input type="number" v-bind:value="data.num" class="number" v-bind:data-realStock="data.realStock" v-on:keyUp="numEntry($index)" v-on:keyDown="numEntry($index)" v-model="data.num"/>
    <span class="add" v-on:click="numChange($index, 1)" v-bind:class="{ 'disable' : data.num==data.realStock }">+</span>
  </div>
</div>

<script src="http://cdn.bootcss.com/vue/1.0.7/vue.js"></script>
<script>
var vue = new Vue({
  el : 'body',
  data : {
    goodsList : [
      {
        name : '山本汉方1',
        price : '19.00',
        realStock : 10,
        num : 1
      },
      {
        name : '山本汉方1',
        price : '19.00',
        realStock : 7,
        num : 8
      },
      {
        name : '山本汉方1',
        price : '19.00',
        realStock : 2,
        num : 2
      },
    ]
  },
  ready : function() {},
  methods : {
    numChange : function(index, numChange) {
      var goods = this.goodsList[index];
      if ( numChange == 1 ) {
        goods.num++;
      } else if ( numChange == -1 ) {
        goods.num--;
      }

      if ( goods.num <= 1 ) {
        goods.num = 1;
      } 

      if ( goods.num >= goods.realStock ) {
        goods.num = goods.realStock;
      }
    },

    numEntry : function(index) {
      var goods = this.goodsList[index];
      if ( goods.num <=1 ) {
        goods.num = 1;
      }

      if ( goods.num > goods.realStock ) {
        goods.num = goods.realStock;
      }

    }
    
  }
})
</script>
</body>
</html>

4.二层数据结构-数据选择器

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuejs-数量选择器(2层数据结构)</title>
<style type="text/css">
*{
  padding:0;
  margin: 0;
  box-sizing: border-box;
  font-size: 16px;
}
a {
  text-decoration: none;
  color: #333;
}
.clearfix:after {
  content: ".";
  visibility: hidden;
  display: block;
  height: .1px;
  font-size: .1em;
  line-height: 0;
  clear: both;
}
.quantity-selector {
  margin: 0 auto;
  width: 8.571rem;
  line-height: 30px;
  border: 1px solid #d1d6e4;
  border-radius: 3px;
}
.quantity-selector .reduce, 
.quantity-selector .add {
  float: left;
  width: 33.33%;
  border-right: 1px solid #d1d6e4;
  text-align: center;
  cursor: pointer;
}
.quantity-selector .number {
  float: left;
  width: 33.33%;
  height: 30px;
  border: none;
  padding-left: 10px;
  text-align: center;
}
.quantity-selector .add {
  border-left: 1px solid #d1d6e4;
  border-right: none;
}
.quantity-selector .disable {
  color: #d2d2d2;
  cursor: default;
}

/*店铺开始*/
.store-item {
  width: 600px;
  margin: 30px auto;
}
.store-item th {
  height: 40px;
  background: #d2d2d2;
  -webkit-text-stroke: 1px #ff7500;
  font-size: 18px;
}
.store-item td {
  height: 60px;
  text-align: center;
}
.cal-store-box {
  text-align: right;
}
.store-footer {
  width: 600px;
  margin: 50px auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
/*店铺结束*/
</style>
</head>
<body>
<div class="store-item" v-for="(index1, item) in goodsObj"> 
  <p v-html="index1"></p>
  <table class="store-item">
    <col width="10%"></col>
    <col width="10%"></col>
    <col width="20%"></col>
    <col width="10%"></col>
    <col width="40%"></col>
    <col width="10%"></col>
    <thead class="thead">
      <tr>
        <th>选择</th>
        <th>商品</th>
        <th>单价</th>
        <th>运费</th>
        <th>数量</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(index, data) in item">
        <td>
          
        </td>
        <td>
          <p><span v-html="data.name"></span></p>
        </td>
        <td v-html="(data.price).toFixed(2)"></td>
        <td v-html="(data.fare).toFixed(2)"></td>
        <td>
          <div class="quantity-selector clearfix">
            <span class="reduce" v-on:click="numChange(index1, $index, -1)" v-bind:class="{ 'disable' : data.num==1 }">-</span>
            <input type="number" v-bind:value="data.num" class="number" v-bind:data-realStock="data.realStock" v-on:keyUp="numEntry(index1, $index)" v-on:keyDown="numEntry(index1, $index)" v-model="data.num"/>
            <span class="add" v-on:click="numChange(index1, $index, 1)" v-bind:class="{ 'disable' : data.num==data.realStock }">+</span>
          </div>
        </td>
        <td>
          <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >删除</a>
        </td>
      </tr>
    </tbody>
  </table>
  <div class="cal-store-box">
    <p>店铺总运费: <span v-html="calEveryFare(index1)"></span></p>
    <p>店铺商品总金额: <span v-html="calEveryStore(index1)"></span></p>
  </div>
</div>

<div class="store-footer">
  <!-- <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
    <input type="checkbox" />
    <span>全选</span>
  </a> -->
  <div class="cal-box">
    <p>商品总金额:<span v-html="totalFare"></span></p>
    <p>运费总金额:<span v-html="totalMoney"></span></p>
  </div>
</div>

<script src="http://cdn.bootcss.com/vue/1.0.7/vue.js"></script>
<script>
var goodsObj = {
  '大胖的店' : [
    {
      name : '康师傅',
      price : 23.00,
      realStock : 10,
      fare : 1.5,
      num : 1
    },

    {
      name : '今麦郎',
      price : 26.00,
      realStock : 2,
      fare : 1.5,
      num : 2
    },

    {
      name : '比巴卜',
      price : 88.00,
      realStock : 8,
      fare : 1.5,
      num : 4
    }
  ],

  '二胖的店' : [
    {
      name : '好看的鞋子',
      price : 23.00,
      realStock : 7,
      fare : 2,
      num : 1
    },

    {
      name : '好看的裙子',
      price : 26.00,
      realStock : 5,
      fare : 2,
      num : 5
    },

    {
      name : '好看的短袖',
      price : 88.00,
      realStock : 10,
      fare : 2,
      num : 1
    }
  ],

  '胖胖的店' : [
    {
      name : '福满多1号',
      price : 26.00,
      realStock : 7,
      fare : 3,
      num : 1
    },

    {
      name : '福满多2号',
      price : 26.00,
      realStock : 7,
      fare : 3,
      num : 1
    },

    {
      name : '经典卫龙辣条',
      price : 16.00,
      realStock : 50,
      fare : 3,
      num : 5
    },

    {
      name : '霸王牛津',
      price : 80.00,
      realStock : 10,
      fare : 3,
      num : 6
    }
  ]
};
var vue = new Vue({
  el : 'body',
  data : {
    goodsObj : goodsObj,
    totalMoney : 0,
    totalFare : 0
  },
  ready : function() {
    this.calTotalMoney();
    this.calTotalFare();
  },
  methods : {
    numChange : function(index1, index, numChange) {
      var goods = this.goodsObj[index1][index],
        oThis = this;
      if ( numChange == 1 ) {
        goods.num++;
      } else if ( numChange == -1 ) {
        goods.num--;
      }

      if ( goods.num <= 1 ) {
        goods.num = 1;
      } 

      if ( goods.num >= goods.realStock ) {
        goods.num = goods.realStock;
      }
      this.calTotalMoney();
    },

    numEntry : function(index1, index) {
      var goods = this.goodsObj[index1][index];
      if ( goods.num <=1 ) {
        goods.num = 1;
      }

      if ( goods.num > goods.realStock ) {
        goods.num = goods.realStock;
      }
      this.calTotalMoney();
    },

    calEveryStore : function(index) {
      var everyStoreMoney = 0;
      this.goodsObj[index].forEach(function(item, index, arr) {
        everyStoreMoney += parseFloat(item.price) * parseFloat(item.num);
      });
      return everyStoreMoney.toFixed(2);
    },

    calEveryFare : function(index) {
      var everyStoreFare = 0;
      this.goodsObj[index].forEach(function(item, index, arr) {
        everyStoreFare += parseFloat(item.fare) * parseFloat(item.num);
      });
      return everyStoreFare.toFixed(2);
    },

    calTotalMoney : function () {
      var oThis = this;
      this.totalMoney = 0;
      for ( var x in this.goodsObj ) {
        this.goodsObj[x].forEach(function(item, index, arr) {
          oThis.totalMoney += parseFloat(item.price) * parseFloat(item.num);
        });
      }
      this.totalMoney = this.totalMoney.toFixed(2);
    },

    calTotalFare : function () {
      var oThis = this;
      this.totalFare = 0;
      for ( var x in this.goodsObj ) {
        this.goodsObj[x].forEach(function(item, index, arr) {
          oThis.totalFare += parseFloat(item.fare) * parseFloat(item.num);
        });
      }
      this.totalFare = this.totalFare.toFixed(2);
    },
    
  }
})
</script>
</body>
</html>

5.一个完整的购物车

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuejs-数量选择器(2层数据结构)</title>
<style type="text/css">
*{
  padding:0;
  margin: 0;
  box-sizing: border-box;
  font-size: 16px;
}
a {
  text-decoration: none;
  color: #333;
}
.clearfix:after {
  content: ".";
  visibility: hidden;
  display: block;
  height: .1px;
  font-size: .1em;
  line-height: 0;
  clear: both;
}
.quantity-selector {
  margin: 0 auto;
  width: 8.571rem;
  line-height: 30px;
  border: 1px solid #d1d6e4;
  border-radius: 3px;
}
.quantity-selector .reduce, 
.quantity-selector .add {
  float: left;
  width: 33.33%;
  border-right: 1px solid #d1d6e4;
  text-align: center;
  cursor: pointer;
}
.quantity-selector .number {
  float: left;
  width: 33.33%;
  height: 30px;
  border: none;
  padding-left: 10px;
  text-align: center;
}
.quantity-selector .add {
  border-left: 1px solid #d1d6e4;
  border-right: none;
}
.quantity-selector .disable {
  color: #d2d2d2;
  cursor: default;
}

label {
  cursor: pointer;
}

.choose-all {
  margin-left: 20px;
}

/*店铺开始*/
.store-item {
  width: 600px;
  margin: 30px auto;
}
.store-item th {
  height: 40px;
  background: #d2d2d2;
  -webkit-text-stroke: 1px #ff7500;
  font-size: 18px;
}
.store-item td {
  height: 60px;
  text-align: center;
}
.cal-store-box {
  text-align: right;
}
.store-footer {
  width: 600px;
  margin: 50px auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
/*店铺结束*/
</style>
</head>
<body>
<div class="store-item" v-for="(index1, item) in goodsObj"> 
  <p>
    <span v-html="item.name"></span>
    <label class="choose-all">
      <input type="checkbox" name="all" v-on:click="chooseShopGoods(index1)" v-model="item.checked" />
      <span>全选</span>
    </label>
  </p>
  <table class="store-item">
    <col width="10%"></col>
    <col width="15%"></col>
    <col width="15%"></col>
    <col width="10%"></col>
    <col width="40%"></col>
    <col width="10%"></col>
    <thead class="thead">
      <tr>
        <th>选择</th>
        <th>商品</th>
        <th>单价</th>
        <th>运费</th>
        <th>数量</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(index, data) in item.list">
        <td>
          <input type="checkbox" name="all" v-model="data.checked" v-on:click="choose(index1, index)" />
        </td>
        <td>
          <p><span v-html="data.name"></span></p>
        </td>
        <td v-html="(data.price).toFixed(2)"></td>
        <td v-html="(data.fare).toFixed(2)"></td>
        <td>
          <div class="quantity-selector clearfix">
            <span class="reduce" v-on:click="numChange(index1, $index, -1)" v-bind:class="{ 'disable' : data.num==1 }">-</span>
            <input type="number" v-bind:value="data.num" class="number" v-bind:data-realStock="data.realStock" v-on:keyUp="numEntry(index1, $index)" v-on:keyDown="numEntry(index1, $index)" v-model="data.num"/>
            <span class="add" v-on:click="numChange(index1, $index, 1)" v-bind:class="{ 'disable' : data.num==data.realStock }">+</span>
          </div>
        </td>
        <td>
          <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" v-on:click="delGoods(index1, index)">删除</a>
        </td>
      </tr>
    </tbody>
  </table>
  <div class="cal-store-box">
    <p>店铺总运费: <span v-html="calEveryFare(index1)"></span></p>
    <p>店铺商品总金额: <span v-html="calEveryStore(index1)"></span></p>
  </div>
</div>

<div class="store-footer">
  <label>
    <input type="checkbox" v-on:click="chooseAllGoods($event)" v-model="allChecked" />
    <span>全选</span>
  </label>
  <div class="cal-box">
    <p>商品总运费:<span v-html="totalFare.toFixed(2)"></span></p>
    <p>商品总金额:<span v-html="totalMoney.toFixed(2)"></span></p>
  </div>
</div>

<script src="http://cdn.bootcss.com/vue/1.0.7/vue.js"></script>
<script>
var goodsObj = [
  {
    name : '大胖的店',
    checked : false,
    list : [
      {
        name : '麻辣二胖',
        price : 23.00,
        realStock : 10,
        fare : 1.5,
        num : 1,
        checked : false,
      },

      {
        name : '香辣二胖',
        price : 21.00,
        realStock : 2,
        fare : 1.5,
        num : 2,
        checked : false,
      },

      {
        name : '红烧二胖',
        price : 88.00,
        realStock : 8,
        fare : 1.5,
        num : 4,
        checked : false,
      }
    ]
  },

  {
    name : '二胖的店',
    checked : false,
    list : [
      {
        name : '漂亮的裙子',
        price : 166.00,
        realStock : 10,
        fare : 2,
        num : 1,
        checked : false,
      },

      {
        name : '漂亮的短袖',
        price : 188.00,
        realStock : 2,
        fare : 1.5,
        num : 2,
        checked : false,
      },

      {
        name : '漂亮的鞋子',
        price : 299.00,
        realStock : 1,
        fare : 3,
        num : 1,
        checked : false,
      }
    ]
  },

  {
    name : '胖胖的店',
    checked : false,
    list : [
      {
        name : '福满多',
        price : 3.00,
        realStock : 10,
        fare : .5,
        num : 10,
        checked : false,
      },

      {
        name : '精品卫龙',
        price : 1.50,
        realStock : 2,
        fare : 2,
        num : 2,
        checked : false,
      },

      {
        name : '周长江',
        price : 2.50,
        realStock : 3,
        fare : 5,
        num : 2,
        checked : false,
      }
    ]
  },
];
var vue = new Vue({
  el : 'body',
  data : {
    goodsObj : goodsObj,
    totalMoney : 0,
    totalFare : 0,
    allChecked : false
  },
  ready : function() {},
  methods : {

    // 全部商品全选
    chooseAllGoods : function() {
      var flag = true;
      if ( this.allChecked ) {
        flag = false;
      }
      for ( var i = 0, len = this.goodsObj.length; i < len; i++ ) {
        this.goodsObj[i]['checked'] = flag;
        var list = this.goodsObj[i]['list'];
        for ( var k = 0, len1 = list.length; k < len1; k++ ) {
          list[k]['checked'] = flag;
        }
      }
      this.allChecked = !this.allChecked;
      this.calTotalMoney();
      this.calTotalFare();
    },

    // 每个店铺全选
    chooseShopGoods : function( index) {
      var list = this.goodsObj[index]['list'],
        len = list.length;
      if ( this.goodsObj[index]['checked'] ) {
        for (var i = 0; i < len; i++ ) {
          list[i]['checked'] = false;
        }
      } else {
        for (var i = 0; i < len; i++ ) {
          list[i]['checked'] = true;
        }
      }
      this.goodsObj[index]['checked'] = !this.goodsObj[index]['checked'];

      // 判断是否选择所有商品的全选
      this.isChooseAll();

      this.cal(index);
    },

    // 单个选择
    choose : function( index1, index) {
      var list = this.goodsObj[index1]['list'],
        len = list.length;
      if ( list[index]['checked'] ) {
        this.goodsObj[index1]['checked'] = false;
        this.allChecked = false;
        list[index]['checked'] = !list[index]['checked'];
      } else {
        list[index]['checked'] = !list[index]['checked'];

        // 判断是否选择当前店铺的全选
        var flag = true;
        for (var i = 0; i < len; i++ ) {
          if ( list[i]['checked'] == false ) {
            flag = false;
            break;
          }
        }
        flag == true ? this.goodsObj[index1]['checked'] = true : this.goodsObj[index1]['checked'] = false;
      }

      // 判断是否选择所有商品的全选
      this.isChooseAll();

      this.cal(index);
    },

    // 判断是否选择所有商品的全选
    isChooseAll : function() {
      var flag1 = true;
      for ( var i = 0, len = this.goodsObj.length; i < len; i++ ) {
        if ( this.goodsObj[i]['checked'] == false ) {
          flag1 = false;
          break;
        }
      }
      flag1 == true ? this.allChecked = true : this.allChecked = false;
    },

    // 商品数量控制
    numChange : function(index1, index, numChange) {
      var goods = this.goodsObj[index1]['list'][index],
        oThis = this;
      if ( numChange == 1 ) {
        goods.num++;
      } else if ( numChange == -1 ) {
        goods.num--;
      }

      if ( goods.num <= 1 ) {
        goods.num = 1;
      } 

      if ( goods.num >= goods.realStock ) {
        goods.num = goods.realStock;
      }

      this.cal(index);
    },

    // 用户填写容错处理
    numEntry : function(index1, index) {
      var goods = this.goodsObj[index1]['list'][index];
      if ( goods.num <=1 ) {
        goods.num = 1;
      }

      if ( goods.num > goods.realStock ) {
        goods.num = goods.realStock;
      }
      this.cal(index);
    },

    // 计算每个店铺的商品总额
    calEveryStore : function(index) {
      var everyStoreMoney = 0,
        list = this.goodsObj[index]['list'];
      list.forEach(function(item, index, arr) {
        if ( list[index]['checked'] ) { 
          everyStoreMoney += parseFloat(item.price) * parseFloat(item.num);
        }
      });
      return everyStoreMoney.toFixed(2);
    },

    // 计算每个店铺的运费总额
    calEveryFare : function(index) {
      var everyStoreFare = 0,
        list = this.goodsObj[index]['list'];
      list.forEach(function(item, index, arr) {
        if ( list[index]['checked'] ) { 
          everyStoreFare += parseFloat(item.fare) * parseFloat(item.num);
        }
      });
      return everyStoreFare.toFixed(2);
    },

    // 计算商品总金额
    calTotalMoney : function () {
      var oThis = this;
      this.totalMoney = 0;
      for ( var i = 0, len = this.goodsObj.length; i < len; i++ ) {
        var list = this.goodsObj[i]['list'];
        list.forEach(function(item, index, arr) {
          if ( list[index]['checked'] ) {
            oThis.totalMoney += parseFloat(item.price) * parseFloat(item.num);
          }
        });
      }
    },

    // 计算商品总运费
    calTotalFare : function () {
      var oThis = this;
      this.totalFare = 0;
      for ( var i = 0, len = this.goodsObj.length; i < len; i++ ) {
        var list = this.goodsObj[i]['list'];
        list.forEach(function(item, index, arr) {
          if ( list[index]['checked'] ) {
            oThis.totalFare += parseFloat(item.fare) * parseFloat(item.num);
          }
        });
      }
    },

    // 计算方法集合
    cal : function(index) {
      this.calEveryStore(index);
      this.calEveryFare(index);
      this.calTotalMoney();
      this.calTotalFare();
    },

    // 删除操作
    delGoods : function(index1, index) {
      console.log(index1);
      console.log(index);
      this.goodsObj[index1]['list'].splice(index, 1);
      this.cal(index);
    }
    
  }
})
</script>
</body>
</html>

效果如下:

vuejs手把手教你写一个完整的购物车实例代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript栏目列表隐藏/显示简单实现
Apr 03 Javascript
js中的异常处理try...catch使用介绍
Sep 21 Javascript
js获取域名的方法
Jan 27 Javascript
jsMind通过鼠标拖拽的方式调整节点位置
Apr 13 Javascript
Node.js项目中调用JavaScript的EJS模板库的方法
Mar 11 Javascript
JS组件Bootstrap实现下拉菜单效果代码
Apr 26 Javascript
通过构造函数实例化对象的方法
Jun 28 Javascript
Vue.js 2.5新特性介绍(推荐)
Oct 24 Javascript
Angular js 实现添加用户、修改密码、敏感字、下拉菜单的综合操作方法
Oct 24 Javascript
vue todo-list组件发布到npm上的方法
Apr 04 Javascript
js实现鼠标拖拽缩放div实例代码
Mar 25 Javascript
详解如何模拟实现node中的Events模块(通俗易懂版)
Apr 15 Javascript
Vue axios 中提交表单数据(含上传文件)
Jul 06 #Javascript
解决webpack打包速度慢的解决办法汇总
Jul 06 #Javascript
详解微信小程序Radio选中样式切换
Jul 06 #Javascript
Node.js 回调函数实例详解
Jul 06 #Javascript
详解vue渲染从后台获取的json数据
Jul 06 #Javascript
微信小程序 Buffer缓冲区的详解
Jul 06 #Javascript
VUE axios发送跨域请求需要注意的问题
Jul 06 #Javascript
You might like
PHP中的strtr函数使用介绍(str_replace)
2011/10/20 PHP
php _autoload自动加载类与机制分析
2012/02/10 PHP
探讨:如何使用PhpDocumentor生成文档
2013/06/25 PHP
php和jquery实现地图区域数据统计展示数据示例
2014/02/12 PHP
PHP利用DWZ.CN服务生成短网址
2019/08/11 PHP
JS的数组的扩展实例代码
2008/07/09 Javascript
SWFObject 2.1以上版本语法介绍
2010/07/10 Javascript
读jQuery之八 包装事件对象
2011/06/21 Javascript
jQuery的控件及事件(输入控件及回车事件)使用示例
2013/07/25 Javascript
ie8本地图片上传预览示例代码
2014/01/12 Javascript
jQuery使用$.get()方法从服务器文件载入数据实例
2015/03/25 Javascript
基于Node的React图片上传组件实现实例代码
2017/05/10 Javascript
微信小程序倒计时功能实例代码
2018/07/17 Javascript
js如何获取图片url的Blob值并预览示例代码
2019/03/07 Javascript
教你完全理解ReentrantLock重入锁
2019/06/03 Javascript
layui字体图标 loading图标静止不旋转的解决方法
2019/09/23 Javascript
[02:46]完美世界DOTA2联赛PWL DAY4集锦
2020/11/03 DOTA
Python实现批量读取word中表格信息的方法
2015/07/30 Python
python 接口_从协议到抽象基类详解
2017/08/24 Python
python GUI实例学习
2017/11/21 Python
python实现画圆功能
2018/01/25 Python
Python selenium实现微博自动登录的示例代码
2018/05/16 Python
Python OpenCV中的resize()函数的使用
2019/06/20 Python
python 元组和列表的区别
2020/12/30 Python
解析HTML5中的新功能本地存储localStorage
2016/03/01 HTML / CSS
美国马匹用品和马钉购物网站:State Line Tack
2018/08/05 全球购物
无传销社区工作方案
2014/05/13 职场文书
护士工作失误检讨书
2014/09/14 职场文书
法人委托书范本
2014/09/15 职场文书
学生上课看漫画的检讨书
2014/09/26 职场文书
个人公司授权委托书范本
2014/10/12 职场文书
2014年实验室工作总结
2014/12/03 职场文书
初中家长评语和期望
2014/12/26 职场文书
法律意见书范文
2015/06/04 职场文书
《花钟》教学反思
2016/02/17 职场文书
python用海龟绘图写贪吃蛇游戏
2021/06/18 Python