用vue编写的购物车案例!!!!(真的学到了很多啊。富含源代码,拿走代码请给个关注哈!)

<!DOCTYPE html>

<html lang="en">

  <head>

    <meta charset="UTF-8" />

    <meta http-equiv="X-UA-Compatible" content="IE=edge" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link rel="stylesheet" href="./css/inputnumber.css" />

    <link rel="stylesheet" href="./css/index.css" />

    <title>小帅购物车</title>

  </head>

  <body>

    <h1>小帅购物车</h1>

    <div class="app-container" id="app">

      <!-- 顶部banner -->

      <div class="banner-box"><img src="http://autumnfish.cn/static/fruit.jpg" alt="" /></div>

      <!-- 面包屑 -->

      <div class="breadcrumb">

        <span>🏠</span>

        /

        <span>购物车</span>

      </div>

      <!-- 购物车主体 -->

      <div class="main" v-if="fruitList.length>0">

        <div class="table">

          <!-- 头部 -->

          <div class="thead">

            <div class="tr">

              <div class="th">选中</div>

              <div class="th th-pic">图片</div>

              <div class="th">单价</div>

              <div class="th num-th">个数</div>

              <div class="th">小计</div>

              <div class="th">操作</div>

            </div>

          </div>

          <!-- 身体 -->

          <div class="tbody" >

            <div class="tr" :class="{active:item.isChecked}" v-for="(item,index) in fruitList" :key="item.id">

              <div class="td"><input type="checkbox" v-model="item.isChecked"/></div>

              <div class="td"><img :src="item.icon" alt="" /></div>

              <div class="td">{{ item.price }}</div>

              <div class="td">

                <div class="my-input-number">

                  <button :disabled="item.num<=1" class="decrease" @click="sub(item.id)"> - </button>

                  <span class="my-input__inner">{{ item.num }}</span>

                  <button class="increase" @click="add(item.id)"> + </button>

                </div>

              </div>

              <div class="td">{{ item.num*item.price }}</div>

              <div class="td"><button @click="del(item.id)">删除</button></div>

            </div>

          </div>

        </div>

        <!-- 底部 -->

        <div class="bottom">

          <!-- 全选 -->

          <label class="check-all">

            <input type="checkbox" v-model="isAll"/>

            全选

          </label>

          <div class="right-box">

            <!-- 所有商品总价 -->

            <span class="price-box">总价&nbsp;&nbsp;:&nbsp;&nbsp;¥&nbsp;<span class="price">{{ totalPrice }}</span></span>

            <!-- 结算按钮 -->

            <button class="pay">结算( {{ totalCount }} )</button>

          </div>

        </div>

      </div>

      <!-- 空车 -->

      <div class="empty" v-else="">🛒空空如也</div>

    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

    <script>

      const defaultArr=[ {

              id: 1,

              icon: 'img/火龙果.png',

              isChecked: true,

              num: 2,

              price: 6,

            },

            {

              id: 2,

              icon: 'img/荔枝.png',

              isChecked: false,

              num: 7,

              price: 20,

            },

            {

              id: 3,

              icon: 'img/榴莲.png',

              isChecked: false,

              num: 3,

              price: 40,

            },

            {

              id: 4,

              icon: 'img/鸭梨.png',

              isChecked: true,

              num: 10,

              price: 3,

            },

            {

              id: 5,

              icon: 'img/樱桃.png',

              isChecked: false,

              num: 20,

              price: 34,

            },]

      const app = new Vue({

        el: '#app',

        data: {

          // 水果列表

          fruitList: JSON.parse(localStorage.getItem("list")) || defaultArr,

        },

        computed:{

          // 默认计算属性:只能获取不能修改

          // isAll(){

          //   // 必须所有小选框都选中,全部按钮才选中》every

          //   return this.fruitList.every(item => item.isChecked)

          // }

            // 完整方法 get+set

          isAll:{

              get(){

                return this.fruitList.every(item => item.isChecked)

              },

              set(value){

                console.log(value)

                // 基于拿到的布尔值,要让所有的小选框同步状态

                // return this.fruitList.every(item => item.isChecked=value)

                this.fruitList.forEach(item => item.isChecked=value);

              }

          },

          // 通计选中总数

          totalCount(){

            return this.fruitList.reduce((sum, item) => {

             return item.isChecked ? sum+ item.num : sum

              // if(item.isChecked){

              //   return sum+item.num

              // }else{

              //   return sum

              // }

            },0)

          },

          //  通计选中的总价 num*price

          totalPrice(){

            return this.fruitList.reduce((sum, item) => {

              return item.isChecked ? sum+ item.num*item.price : sum

            },0)

          }

        },

        methods:{

          del(id){

            this.fruitList=this.fruitList.filter(item => item.id!==id)

          },

          sub(id){

            // 根据id找到数组中的对应项》find

            const fruit=this.fruitList.find(item => item.id===id)

            // 操作num数量

           fruit.num--

          },

          add(id){

            const fruit=this.fruitList.find(item => item.id===id)

            // 操作num数量

           fruit.num++

          }

        },

        watch:{

          fruitList:{

            deep:true,

            handler(newValue){

                // console.log(newValue);

                // 变化后的newvalue存入本地 (转json)

                localStorage.setItem("list",JSON.stringify(newValue))

            }

          }

        }

      })

    </script>

  </body>

</html>

以下是css代码有点长!!!!!!!!!!!!!!!!!

.my-input-number {

  position: relative;

  display: inline-block;

  width: 140px;

  line-height: 38px;

}

.my-input-number span {

  -moz-user-select: none;

  -webkit-user-select: none;

  -ms-user-select: none;

}

.my-input-number .my-input {

  display: block;

  position: relative;

  font-size: 14px;

  width: 100%;

}

.my-input-number .my-input__inner {

  -webkit-appearance: none;

  background-color: #fff;

  background-image: none;

  border-radius: 4px;

  border: 1px solid #dcdfe6;

  box-sizing: border-box;

  color: #606266;

  display: inline-block;

  font-size: inherit;

  height: 40px;

  line-height: 40px;

  outline: none;

  padding: 0 15px;

  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);

  width: 100%;

  padding-left: 50px;

  padding-right: 50px;

  text-align: center;

}

.my-input-number .my-input-number__decrease,

.my-input-number .my-input-number__increase {

  position: absolute;

  z-index: 1;

  top: 1px;

  width: 40px;

  height: auto;

  text-align: center;

  background: #f5f7fa;

  color: #606266;

  cursor: pointer;

  font-size: 13px;

}

.my-input-number .my-input-number__decrease {

  left: 1px;

  border-radius: 4px 0 0 4px;

  border-right: 1px solid #dcdfe6;

}

.my-input-number .my-input-number__increase {

  right: 1px;

  border-radius: 0 4px 4px 0;

  border-left: 1px solid #dcdfe6;

}

.my-input-number .my-input-number__decrease.is-disabled,

.my-input-number .my-input-number__increase.is-disabled {

  color: #c0c4cc;

  cursor: not-allowed;

}

以下是第二个css代码!!!!!!!!!!!!!!!!!

.app-container {

  padding-bottom: 300px;

  width: 800px;

  margin: 0 auto;

}

@media screen and (max-width: 800px) {

  .app-container {

    width: 600px;

  }

}

.app-container .banner-box {

  border-radius: 20px;

  overflow: hidden;

  margin-bottom: 10px;

}

.app-container .banner-box img {

  width: 100%;

}

.app-container .nav-box {

  background: #ddedec;

  height: 60px;

  border-radius: 10px;

  padding-left: 20px;

  display: flex;

  align-items: center;

}

.app-container .nav-box .my-nav {

  display: inline-block;

  background: #5fca71;

  border-radius: 5px;

  width: 90px;

  height: 35px;

  color: white;

  text-align: center;

  line-height: 35px;

  margin-right: 10px;

}

.breadcrumb {

  font-size: 16px;

  color: gray;

}

.table {

  width: 100%;

  text-align: left;

  border-radius: 2px 2px 0 0;

  border-collapse: separate;

  border-spacing: 0;

}

.th {

  color: rgba(0, 0, 0, 0.85);

  font-weight: 500;

  text-align: left;

  background: #fafafa;

  border-bottom: 1px solid #f0f0f0;

  transition: background 0.3s ease;

}

.th.num-th {

  flex: 1.5;

}

.th {

  text-align: center;

}

.th:nth-child(4),

.th:nth-child(5),

.th:nth-child(6),

.th:nth-child(7) {

  text-align: center;

}

.th.th-pic {

  flex: 1.3;

}

.th:nth-child(6) {

  flex: 1.3;

}

.th,

.td {

  position: relative;

  padding: 16px 16px;

  overflow-wrap: break-word;

  flex: 1;

}

.pick-td {

  font-size: 14px;

}

.main,

.empty {

  border: 1px solid #f0f0f0;

  margin-top: 10px;

}

.tr {

  display: flex;

  cursor: pointer;

  border-bottom: 1px solid #ebeef5;

}

.tr.active {

  background-color: #f5f7fa;

}

.td {

  display: flex;

  justify-content: center;

  align-items: center;

}

.table img {

  width: 100px;

  height: 100px;

}

button {

  outline: 0;

  box-shadow: none;

  color: #fff;

  background: #d9363e;

  border-color: #d9363e;

  color: #fff;

  background: #d9363e;

  border-color: #d9363e;

  line-height: 1.5715;

  position: relative;

  display: inline-block;

  font-weight: 400;

  white-space: nowrap;

  text-align: center;

  background-image: none;

  border: 1px solid transparent;

  box-shadow: 0 2px 0 rgb(0 0 0 / 2%);

  cursor: pointer;

  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);

  -webkit-user-select: none;

  -moz-user-select: none;

  -ms-user-select: none;

  user-select: none;

  touch-action: manipulation;

  height: 32px;

  padding: 4px 15px;

  font-size: 14px;

  border-radius: 2px;

}

button.pay {

  background-color: #3f85ed;

  margin-left: 20px;

}

.bottom {

  height: 60px;

  display: flex;

  align-items: center;

  justify-content: space-between;

  padding-right: 20px;

  border: 1px solid #f0f0f0;

  border-top: none;

  padding-left: 20px;

}

.right-box {

  display: flex;

  align-items: center;

}

.check-all {

  cursor: pointer;

}

.price {

  color: hotpink;

  font-size: 30px;

  font-weight: 700;

}

.price-box {

  display: flex;

  align-items: center;

}

.empty {

  padding: 20px;

  text-align: center;

  font-size: 30px;

  color: #909399;

}

.my-input-number {

  display: flex;

}

.my-input-number button {

  height: 40px;

  color: #333;

  border: 1px solid #dcdfe6;

  background-color: #f5f7fa;

}

.my-input-number button:disabled {

  cursor: not-allowed!important;

}

.my-input-number .my-input__inner {

  height: 40px;

  width: 50px;

  padding: 0;

  border: none;

  border-top: 1px solid #dcdfe6;

  border-bottom: 1px solid #dcdfe6;

}

h1{

  text-align: center;

  font-size: 60px;

  color: skyblue;

}

 图片的话请大家自行网上下载哈!!!!这里只提供部分水果图片,仅供大家测试!!!1

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风流野趣fly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值