Vue-购物车案例(非常详细)

学习目标

  • 初始代码
    • 提供了数据,页面内容和页面样式
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <style>
        .fl{
            float: left;
        }
        .fr{
            float: right;
        }
       blockquote, body, dd, div, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, img, input, li, ol, p, table, td, textarea, th, ul {
            margin: 0;
            padding: 0;
        }
       .clearfix{
          zoom: 1;
       }
        .clearfix:after {
            clear: both;
        }
        .clearfix:after {
            content: '.';
            display: block;
            overflow: hidden;
            visibility: hidden;
            font-size: 0;
            line-height: 0;
            width: 0;
            height: 0;
        }
        a{
            text-decoration: none;
            color: #333;
        }
        img{vertical-align: middle;}
        .page-shopping-cart {
            width: 1200px;
            margin: 50px auto;
            font-size: 14px;
            border: 1px solid #e3e3e3;
            border-top: 2px solid #317ee7; }
        .page-shopping-cart .cart-title {
            color: #317ee7;
            font-size: 16px;
            text-align: left;
            padding-left: 20px;
            line-height: 68px; }
        .page-shopping-cart .red-text {
            color: #e94826; }
        .page-shopping-cart .check-span {
            display: block;
            width: 24px;
            height: 20px;
            background: url("shopping_cart.png") no-repeat 0 0; }
        .page-shopping-cart .check-span.check-true {
            background: url("shopping_cart.png") no-repeat 0 -22px; }
        .page-shopping-cart .td-check {
            width: 70px; }
        .page-shopping-cart .td-product {
            width: 460px; }
        .page-shopping-cart .td-num, .page-shopping-cart .td-price, .page-shopping-cart .td-total {
            width: 160px; }
        .page-shopping-cart .td-do {
            width: 150px; }
        .page-shopping-cart .cart-product-title {
            text-align: center;
            height: 38px;
            line-height: 38px;
            padding: 0 20px;
            background: #f7f7f7;
            border-top: 1px solid #e3e3e3;
            border-bottom: 1px solid #e3e3e3; }
        .page-shopping-cart .cart-product-title .td-product {
            text-align: center;
            font-size: 14px; }
        .page-shopping-cart .cart-product-title .td-check {
            text-align: left; }
        .page-shopping-cart .cart-product-title .td-check .check-span {
            margin: 9px 6px 0 0; }
        .page-shopping-cart .cart-product {
            padding: 0 20px;
            text-align: center; }
        .page-shopping-cart .cart-product table {
            width: 100%;
            text-align: center;
            font-size: 14px; }
        .page-shopping-cart .cart-product table td {
            padding: 20px 0; }
        .page-shopping-cart .cart-product table tr {
            border-bottom: 1px dashed #e3e3e3; }
        .page-shopping-cart .cart-product table tr:last-child {
            border-bottom: none; }
        .page-shopping-cart .cart-product table .product-num {
            border: 1px solid #e3e3e3;
            display: inline-block;
            text-align: center; }
        .page-shopping-cart .cart-product table .product-num .num-do {
            width: 24px;
            height: 28px;
            display: block;
            background: #f7f7f7; }
        .page-shopping-cart .cart-product table .product-num .num-reduce span {
            background: url("shopping_cart.png") no-repeat -40px -22px;
            display: block;
            width: 6px;
            height: 2px;
            margin: 13px auto 0 auto; }
        .page-shopping-cart .cart-product table .product-num .num-add span {
            background: url("shopping_cart.png") no-repeat -60px -22px;
            display: block;
            width: 8px;
            height: 8px;
            margin: 10px auto 0 auto; }
        .page-shopping-cart .cart-product table .product-num .num-input {
            width: 42px;
            height: 28px;
            line-height: 28px;
            border: none;
            text-align: center; }
        .page-shopping-cart .cart-product table .td-product {
            text-align: left;
            font-size: 12px;
            line-height: 20px; }
        .page-shopping-cart .cart-product table .td-product img {
            border: 1px solid #e3e3e3;
            margin-right: 10px; }
        .page-shopping-cart .cart-product table .td-product .product-info {
            display: inline-block;
            vertical-align: middle; }
        .page-shopping-cart .cart-product table .td-do {
            font-size: 12px; }
        .page-shopping-cart .cart-product-info {
            height: 50px;
            line-height: 50px;
            background: #f7f7f7;
            padding-left: 20px; }
        .page-shopping-cart .cart-product-info .delect-product {
            color: #666; }
        .page-shopping-cart .cart-product-info .delect-product span {
            display: inline-block;
            vertical-align: top;
            margin: 18px 8px 0 0;
            width: 13px;
            height: 15px;
            background: url("shopping_cart.png") no-repeat -60px 0; }
        .page-shopping-cart .cart-product-info .product-total {
            font-size: 14px;
            color: #e94826; }
        .page-shopping-cart .cart-product-info .product-total span {
            font-size: 20px; }
        .page-shopping-cart .cart-product-info .check-num {
            color: #333; }
        .page-shopping-cart .cart-product-info .check-num span {
            color: #e94826; }
        .page-shopping-cart .cart-product-info .keep-shopping {
            color: #666;
            margin-left: 40px; }
        .page-shopping-cart .cart-product-info .keep-shopping span {
            display: inline-block;
            vertical-align: top;
            margin: 18px 8px 0 0;
            width: 15px;
            height: 15px;
            background: url("shopping_cart.png") no-repeat -40px 0; }
        .page-shopping-cart .cart-product-info .btn-buy {
            height: 50px;
            color: #fff;
            font-size: 20px;
            display: block;
            width: 110px;
            background: #ff7700;
            text-align: center;
            margin-left: 30px; }
        .page-shopping-cart .cart-worder {
            padding: 20px; }
        .page-shopping-cart .cart-worder .choose-worder {
            color: #fff;
            display: block;
            background: #39e;
            width: 140px;
            height: 40px;
            line-height: 40px;
            border-radius: 4px;
            text-align: center;
            margin-right: 20px; }
        .page-shopping-cart .cart-worder .choose-worder span {
            display: inline-block;
            vertical-align: top;
            margin: 9px 10px 0 0;
            width: 22px;
            height: 22px;
            background: url("shopping_cart.png") no-repeat -92px 0; }
        .page-shopping-cart .cart-worder .worker-info {
            color: #666; }
        .page-shopping-cart .cart-worder .worker-info img {
            border-radius: 100%;
            margin-right: 10px; }
        .page-shopping-cart .cart-worder .worker-info span {
            color: #000; }

        .choose-worker-box {
            width: 620px;
            background: #fff; }
        .choose-worker-box .box-title {
            height: 40px;
            line-height: 40px;
            background: #F7F7F7;
            text-align: center;
            position: relative;
            font-size: 14px; }
        .choose-worker-box .box-title a {
            display: block;
            position: absolute;
            top: 15px;
            right: 16px;
            width: 10px;
            height: 10px;
            background: url("shopping_cart.png") no-repeat -80px 0; }
        .choose-worker-box .box-title a:hover {
            background: url("shopping_cart.png") no-repeat -80px -22px; }
        .choose-worker-box .worker-list {
            padding-top: 30px;
            height: 134px;
            overflow-y: auto; }
        .choose-worker-box .worker-list li {
            float: left;
            width: 25%;
            text-align: center;
            margin-bottom: 30px; }
        .choose-worker-box .worker-list li p {
            margin-top: 8px; }
        .choose-worker-box .worker-list li.cur a {
            color: #f70; }
        .choose-worker-box .worker-list li.cur a img {
            border: 1px solid #f70; }
        .choose-worker-box .worker-list li a:hover {
            color: #f70; }
        .choose-worker-box .worker-list li a:hover img {
            border: 1px solid #f70; }
        .choose-worker-box .worker-list li img {
            border: 1px solid #fff;
            border-radius: 100%; }
    style>
head>
<body>
<div class="page-shopping-cart" id="shopping-cart">
    <h4 class="cart-title">购物清单h4>
    <div class="cart-product-title clearfix">
        <div class="td-check fl"><span class="check-span fl check-all">span>全选div>
        <div class="td-product fl">商品div>
        <div class="td-num fl">数量div>
        <div class="td-price fl">单价(元)div>
        <div class="td-total fl">金额(元)div>
        <div class="td-do fl">操作div>
    div>
    <div class="cart-product clearfix">
        <table>
            <tbody><tr>
                <td class="td-check"><span class="check-span">span>td>
                <td class="td-product"><img src="./images/testimg.png" width="98" height="98">
                    <div class="product-info">
                        <h6>【斯文】甘油 | 丙三醇h6>
                        <p>品牌:韩国skc  产地:韩国p>
                        <p>规格/纯度:99.7%  起定量:215千克p>
                        <p>配送仓储:上海仓海仓储p>
                    div>
                    <div class="clearfix">div>
                td>
                <td class="td-num">
                    <div class="product-num">
                        <a href="javascript:;" class="num-reduce num-do fl"><span>span>a>
                        <input type="text" class="num-input" value="3">
                        <a href="javascript:;" class="num-add num-do fr"><span>span>a>
                    div>
                td>
                <td class="td-price">
                    <p class="red-text"><span class="price-text">800span>.00p>
                td>
                <td class="td-total">
                    <p class="red-text"><span class="total-text">800span>.00p>
                td>
                <td class="td-do"><a href="javascript:;" class="product-delect">删除a>td>
            tr>
            <tr>
                <td class="td-check"><span class="check-span check-true">span>td>
                <td class="td-product"><img src="./images/testimg.png" width="98" height="98">
                    <div class="product-info">
                        <h6>【斯文】甘油 | 丙三醇h6>
                        <p>品牌:韩国skc  产地:韩国p>
                        <p>规格/纯度:99.7%  起定量:215千克p>
                        <p>配送仓储:上海仓海仓储p>
                    div>
                    <div class="clearfix">div>
                td>
                <td class="td-num">
                    <div class="product-num">
                        <a href="javascript:;" class="num-reduce num-do fl"><span>span>a>
                        <input type="text" class="num-input" value="1">
                        <a href="javascript:;" class="num-add num-do fr"><span>span>a>
                    div>
                td>
                <td class="td-price">
                    <p class="red-text"><span class="price-text">800span>.00p>
                td>
                <td class="td-total">
                    <p class="red-text"><span class="total-text">800span>.00p>
                td>
                <td class="td-do"><a href="javascript:;" class="product-delect">删除a>td>
            tr>
            tbody>table>
    div>
    <div class="cart-product-info">
        <a class="delect-product" href="javascript:;"><span>span>删除所选商品a>
        <a class="keep-shopping" href="#"><span>span>继续购物a>
        <a class="btn-buy fr" href="javascript:;">去结算a>
        <p class="fr product-total"><span>1600span>p>
        <p class="fr check-num"><span>2span>件商品总计(不含运费):p>
    div>
    <div class="cart-worder clearfix">
        <a href="javascript:;" class="choose-worder fl"><span>span>绑定跟单员a>
        <div class="worker-info fl">
        div>
    div>
div>
body>
<script>
    new Vue({
        el:'#shopping-cart',
        data:{
            productList: [
                {
                    'pro_name': '【斯文】甘油 | 丙三醇 --1',//产品名称
                    'pro_brand': 'skc',//品牌名称
                    'pro_place': '韩国',//产地
                    'pro_purity': '99.7%',//规格
                    'pro_min': "215千克",//最小起订量
                    'pro_depot': '上海仓海仓储',//所在仓库
                    'pro_num': 3,//数量
                    'pro_img': './images/testimg.png',//图片链接
                    'pro_price': 800,//单价
                    'select':true //是否选中
                },
                {
                    'pro_name': '【斯文】甘油 | 丙三醇 --2',//产品名称
                    'pro_brand': 'skc',//品牌名称
                    'pro_place': '韩国',//产地
                    'pro_purity': '99.7%',//规格
                    'pro_min': "215千克",//最小起订量
                    'pro_depot': '上海仓海仓储',//所在仓库
                    'pro_num': 3,//数量
                    'pro_img': './images/testimg.png',//图片链接
                    'pro_price': 800,//单价
                    'select':false //是否选中
                },
                {
                    'pro_name': '【斯文】甘油 | 丙三醇 --3',//产品名称
                    'pro_brand': 'skc',//品牌名称
                    'pro_place': '韩国',//产地
                    'pro_purity': '99.7%',//规格
                    'pro_min': "215千克",//最小起订量
                    'pro_depot': '上海仓海仓储',//所在仓库
                    'pro_num': 3,//数量
                    'pro_img': './images/testimg.png',//图片链接
                    'pro_price': 800,//单价
                    'select':true //是否选中
                }
            ]
        },
        computed: {},
        methods:{
            
        }
    })
script>
html>
  • 页面展示

Vue-购物车案例(非常详细)_第1张图片

  • 要求
    • 实现全选,选中购物车中所有内容
    • 点击增加和减少按钮,每个商品的数量发生变化,对应的金额会变化
    • 动态计算总价,商品总数
    • 点击操作中的删除,或者下面的删除所选商品按钮可以删除商品

工作开始

初步分析

  1. 首先我们看这个代码,它是没有引入vue.js的,所以我们的第一步当然是先引入一下
```html

```
  • 注意,引入必须在我们要写的script标签前,不然vue.js在功能模块后引入的话,功能模块是找不到vue.js
  1. 第二步当然是把页面稍微修改修改,让它适合我们使用vue来进行操作
    1. 先把购物车商品模块删掉多余的,只留下一个当做模板
    2. 使用v-for调用dataproductList列表里的数据,循环创建元素
    3. 将循环出来的product数据通过插值表达式{{}}展现在页面上
    4. 使用v-bindproduct里的pro_img(图片地址)绑定到img里的src
    5. 使用v-modelproduct里的pro_num(商品数量)和input进行双向绑定,以便修改商品数量
                 
                 
                 
                 <tr v-for="product in productList">
                     <td class="td-check"><span class="check-span">span>td>
                     
                     
                     <td class="td-product"><img v-bind:src="product.pro_img" width="98" height="98">
                         
                         
                         <div class="product-info">
                             <h6>{{ product.pro_name }}h6>
                             <p>品牌:{{ product.pro_place }}{{ product.pro_brand }}  产地:{{ product.pro_place }}p>
                             <p>规格/纯度:{{ product.pro_purity }}  起定量:{{ product.pro_min }}p>
                             <p>配送仓储:{{ product.pro_depot }}p>
                         div>
                         <div class="clearfix">div>
                     td>
                     <td class="td-num">
                         <div class="product-num">
                             <a href="javascript:;" class="num-reduce num-do fl"><span>span>a>
                             
                             
                             <input type="text" class="num-input" v-model="product.pro_num">
                             <a href="javascript:;" class="num-add num-do fr"><span>span>a>
                         div>
                     td>
                     
                     
                     <td class="td-price">
                         <p class="red-text"><span class="price-text">{{ product.pro_price }}span>.00p>
                     td>
                     <td class="td-total">
                         <p class="red-text"><span class="total-text">{{ product.pro_num * product.pro_price }}span>.00p>
                     td>
                     <td class="td-do"><a href="javascript:;" class="product-delect">删除a>td>
                 tr>
    

效果展示

Vue-购物车案例(非常详细)_第2张图片

要求实现

  1. 我们首先来实现简单的删除功能
    1. 首先分析一下,商品删除的本质是什么,那当然是列表删除,因为我们的数据都是从data里的productList列表中获取的
    2. 列表删除通常使用splice()方法,而该方法需要传俩个参数,一个就是下标索引,一个就是删除的个数,删除个数毋庸置疑是1嘛,一次删一个,那么我们需要的数据就很明显了,index下标
    
    <tr v-for="(product, index) in productList">
    ...
    
    <td class="td-do"><a href="javascript:;" class="product-delect" @click="btnClose(index)">删除a>td>
    tr>
    ...
      <script>
          new Vue({
              ...
              methods: {
                  <!-- 通过传进来的下标,用splice方法将该下标的数据从productList列表中删除 -->
                  btnClose(index) {
                      this.productList.splice(index, 1)
                  }
              }
          })
      script>
    

效果展示

Vue-购物车案例(非常详细)_第3张图片

Vue-购物车案例(非常详细)_第4张图片

  1. 然后是商品选中,主要还是看select属性,为true则为选中,为false则为不选中,那么我们只要判断select属性到底是什么就好了,然后再加个点击事件改变select属性,这个功能就完成了
<tr v-for="(item,index) in productList">
              
              
              
              <td class="td-check"><span class="check-span" @click="product.select=!product.select" :class="{'check-true':product.select}">span>td>
              ...
tr>

效果展示

Vue-购物车案例(非常详细)_第5张图片

Vue-购物车案例(非常详细)_第6张图片

  1. 既然我们能选中了,那么就来删除所选

    1. 首先思考的就是所选,既然是删除所选,那么当然得判断一下它是不是所选,是true则为选中那么删除,是false则为不选中那么就不动
    <div class="cart-product-info">
         
         <a class="delect-product" href="javascript:;" @click="closeSelect"><span>span>删除所选商品a>
         ...
     div>
       ...
     <script>
         new Vue({
             ...
             methods: {
             <!-- 这里使用了filter过滤器,其本质就是将每个数据单独提出来,为true的则删掉 -->
             closeSelect() {
                 this.productList=this.productList.filter(function (product) {return !product.select})
             }
             }
         })
     script>
    

    效果展示

Vue-购物车案例(非常详细)_第7张图片

Vue-购物车案例(非常详细)_第8张图片

  1. 再下一步就是可以改变数量,同时商品金额动态改变

    1. 这个功能相对简单很多,其本质就是productpro_num值的改变和简单的数学运算
    ...
    <td class="td-num">
        <div class="product-num">
               
               <a href="javascript:;" class="num-reduce num-do fl" @click="product.pro_num>0?product.pro_num--:''"><span>span>a>
               <input type="text" class="num-input" v-model="product.pro_num">
               
               <a href="javascript:;" class="num-add num-do fr" @click="product.pro_num++"><span>span>a>
        div>
    td>
    ...
    <td class="td-total">
               
               <p class="red-text"><span class="total-text">{{product.pro_price*product.pro_num}}span>.00p>
    td>
    ...
    

    效果展示

Vue-购物车案例(非常详细)_第9张图片

  1. 然后就是动态数量动态总价
    1. 动态数量动态总价,其计算的都是被选中的商品,也就是select值为true的,所以只要从这里入手就好了
    2. 动态总价,就是被选中的商品总价
    3. 动态数量,很好理解,被选中的商品数量,可以在计算动态总价的时候顺带着完成
    ...
         <div class="cart-product-info">
             ...
             
             <p class="fr product-total"><span>{{ getTotal.totalPrice }}span>p>
             <p class="fr check-num"><span>{{ getTotal.totalNum }}span>件商品总计(不含运费):p>
         div>
         ...
    <script>
    new Vue({
    ...
    computed: {
         getTotal() {
             // 获取productList中select为true的数据
             var proList = this.productList.filter(
                 function(val) {
                     return val.select
                 });
             // 设置一个值用来存储总价
             var totalPrice = 0;
             for (let i = 0; i < proList.length; i++) {
                 // 将每个商品的总价加在一起
                 totalPrice += proList[i].pro_num * proList[i].pro_price;
             };
             return {
                 // 被选中的物品数量就是proList.length
                 totalNum: proList.length,
                 // 总价就是totalPrice
                 totalPrice: totalPrice
             }
         },
         ...
    })
    script>
    
    效果展示

Vue-购物车案例(非常详细)_第10张图片

  1. 兄弟们,就剩最后一个全选反选了,冲呀

    1. 这个就有点绕了,需要做判断,当非全选时,点击全选是将剩下没选中的商品选中,当所有商品被选中时,点击才是反选
    2. 同时,当商品为全选中状态时,全选自动勾上,否则则不勾
    3. every()方法,针对数组中的每一个元素进行比对,只要有一个元素比对结果为false则返回false,反之要所有的元素比对结果为true才为true
        ...
        <div class="cart-product-title clearfix">
            
            
            <div class="td-check fl"><span class="check-span fl check-all" :class="{'check-true':isSelectAll}" @click="selectProduct(isSelectAll)">span>全选div>
            ...
        div>
        ...
        <script>
        new Vue({
         computed: {
            //检测是否全选
            isSelectAll: function() {
                //如果长度为0,直接返回false
                if (this.productList.length === 0) {
                    return false;
                }
                //如果productList中每一条数据的select都为true,返回true,否则返回false;
                return this.productList.every(function(val) {
                    return val.select
                });
            },
            ...
         },
         methods: {
            //全选与取消全选
            selectProduct: function(isSelect) {
                //遍历productList,全部取反
                for (var i = 0, len = this.productList.length; i < len; i++) {
                    //让productList[i].select不管为true还是false都取!isSelect,如现在未全选,那么isSelect就为false,!isSelect就为true,所以点击让商品的select都变为true
                    this.productList[i].select = !isSelect;
                }
            },
            ...
        })
        script>
    

    效果展示

Vue-购物车案例(非常详细)_第11张图片
Vue-购物车案例(非常详细)_第12张图片

最后总结

这个项目并不算太难,主要锻炼初学者的逻辑思维能力吧
得有想法,才能有作为嘛
首先得知道要干什么,才能找准方向冲他丫的,不怕有问题,有问题就解决嘛,不会就学嘛,就怕找不着方向,迷茫了
不过我相信兄弟们肯定都比我牛,所以肯定不会这样的
再见啦,希望能帮到不认识的你,希望能点个赞,让我知道我帮到你,我会挺开心的

你可能感兴趣的:(Vue,前端,vue.js,javascript,前端)