基于Vue组件 实现购物车案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src='./js/vue.js'></script>
    <style type="text/css">
      .container {
      }
      .container .cart {
        width: 300px;
        margin: auto;
      }
      .container .title {
        background-color: lightblue;
        height: 40px;
        line-height: 40px;
        text-align: center;
      }
      .container .total {
        background-color: #FFCE46;
        height: 50px;
        line-height: 50px;
        text-align: right;
      }
      .container .total button {
        margin: 0 10px;
        background-color: #DC4C40;
        height: 35px;
        width: 80px;
        border: 0;
      }
      .container .total span {
        color: red;
        font-weight: bold;
      }
      .container .item {
        height: 55px;
        line-height: 55px;
        position: relative;
        border-top: 1px solid #ADD8E6;
      }
      .container .item img {
        width: 45px;
        height: 45px;
        margin: 5px;
      }
      .container .item .name {
        position: absolute;
        width: 90px;
        top: 0;left: 55px;
        font-size: 16px;
      }
  
      .container .item .change {
        width: 100px;
        position: absolute;
        top: 0;
        right: 50px;
      }
      .container .item .change a {
        font-size: 20px;
        width: 30px;
        text-decoration:none;
        background-color: lightgray;
        vertical-align: middle;
      }
      .container .item .change .num {
        width: 40px;
        height: 25px;
      }
      .container .item .del {
        position: absolute;
        top: 0;
        right: 0px;
        width: 40px;
        text-align: center;
        font-size: 40px;
        cursor: pointer;
        color: red;
      }
      .container .item .del:hover {
        background-color: orange;
      }
    </style>
</head>
<body>
<section id="app">
  <div class='container'>
    <my-cart></my-cart>
  </div>
</section>
<script type="text/javascript">
  var cartTitle= {
    props: ['uname'],
    template: `
    <div class='title'>
      {{uname}}商品
    </div>
    `
  }
  var cartList= {
    props: ['list'],
    template: `
    <div>
      <div class="item" :key='item.id' v-for='item in list'>
        <img :src='item.img'/>
        <div class="name">{{ item.name }}</div>
        <div class="change">
          <a href="" v-on:click.prevent='sub(item.id)'></a>
          <input type="text" class="num" :value='item.num' v-on:blur='changeNum(item.id, $event)'/>
          <a href="" v-on:click.prevent='add(item.id)'></a>
        </div>
        <div class="del" v-on:click='del(item.id)'>×</div>
      </div>
    </div>
    `,
    methods: {
      del: function(id){
        // 把id传递给父组件
        this.$emit('cart-del', id);
      },
      changeNum: function(id, event){
        this.$emit('change-num', {
          id: id,
          type: 'change',
          num: event.target.value
        });
        // console.log(id, event.target.value);
      },
      sub: function(id){
        this.$emit('change-num', {
          id: id,
          type: 'sub'
        });
      },
      add: function(id){
        this.$emit('change-num', {
          id: id,
          type: 'add'
        });
      }
    }
  }
  var cartTotal= {
    props: ['list'],
    template: `
    <div class='total'>
      <span>总价:{{ total }}</span>
      <button>结算</button>
    </div>
    `,
    computed: {
      total: function(){
        // 计算商品的总价
        var t= 0;
        this.list.map(item=> {
          t+= item.price* item.num;
        });
        return t;
      }
    }
  }
  Vue.component('my-cart', {
      data: function(){
        return {
          uname: '马云的',
          list: [{
            id: 1,
            name: 'TCL彩电',
            price: 1000,
            num: 1,
            img: 'img/a.jpg'
          },{
            id: 2,
            name: '机顶盒',
            price: 1000,
            num: 1,
            img: 'img/b.jpg'
          },{
            id: 3,
            name: '海尔冰箱',
            price: 1000,
            num: 1,
            img: 'img/c.jpg'
          },{
            id: 4,
            name: '小米手机',
            price: 1200,
            num: 1,
            img: 'img/d.jpg'
          },{
            id: 5,
            name: 'PPTV电视',
            price: 1000,
            num: 2,
            img: 'img/e.jpg'
          }]
        }
      },
      template: `
        <div class='cart'>
          <cart-title :uname='uname'></cart-title>
          <cart-list :list='list' v-on:cart-del='delCart($event)' v-on:change-num='changeNum($event)'></cart-list>
          <cart-total :list='list'></cart-total>
        </div>
      `,
      components: {
        'cart-title': cartTitle,
        'cart-list': cartList,
        'cart-total': cartTotal,
      },
      methods: {
        delCart: function(id){
          // 根据id删除list中对应的数据
          // 1、找到id所对应数据的索引
          // 2、根据索引,删除对应数据
          var index= this.list.findIndex(function(item){
            return item.id == id;
          });
          this.list.splice(index, 1);

          // this.list= this.list.filter(function(item){
          //   return item.id != id;
          // })
        },
        changeNum: function(val){
          // console.log(val);
          // 根据子组件传过来的数据,更新list中对应的数据
          this.list.some(function(item){
            if(item.id== val.id && val.type== 'change'){
              item.num= val.num;
              // 终止遍历
              return true;
            }else if(item.id== val.id &&  val.type== 'sub'){
              item.num> 0? item.num--: 0;
              return true;
            }else if(item.id== val.id &&  val.type== 'add'){
              item.num< 99? item.num++: 99;
              return true;
            }
          })
        },
      }
    });
  var vm = new Vue({
      el: '#app',
      data: {
        
      }
    });
</script>
</body>
</html>

 

posted @ 2020-09-07 20:44  wing1377  阅读(661)  评论(0编辑  收藏  举报