zoukankan      html  css  js  c++  java
  • Vue(小案例_vue+axios仿手机app)_购物车(二模拟淘宝购物车页面,点击加减做出相应变化)

    一、前言                                                                             

    在上篇购物车中,如果用户刷新了当前的页面,底部导航中的数据又会恢复为原来的:

                                                              1、解决刷新,购物车上数值不变

                                                              2、在购物车点击加减按钮,数值做出对应变化

    二、主要内容                                                                      

    1、实现效果:点击购物车的时候可以查看到购物车的商品信息

    2、解决刷新,购物车上数值不变

      (1)新建一个Cart.vue展示购物信息,并将路由添加到index.js中

      (2)购物车里面涉及到:存储商品信息,获取商品信息,保存商品信息,这里将这些方法单独封装到一个.js文件中(本来需要在后台操作)

    let obj={}; //定义一个对象,存储商品信息
    
    //这里需要存储数据
    //{商品的id, 商品的数量}
    
    //保存商品
    obj.saveGoods = function(goodsList){
        window.localStorage.setItem('goodsList',JSON.stringify(goodsList))
    }
    
    
    //获取商品的值
    obj.getGoodsList = function(){
        return JSON.parse(window.localStorage.getItem('goodsList'|| '{}'))//如果stroge中没有值,返回一个空对象
    }
    
    //增加商品
    obj.add = function(goods){
        let goodsList = this.getGoodsList()//获取到storage里面的对象
        if(goodsList[goods.id]){
    
            //goods.id是商品的数量,对应有值的话就追加
            goodsList[goods.id] = goodsList[goods.id] + goods.num;  
        }else{
            goodsList[goods.id]=goods.num;
        }
    
        //传进来之后还需要保存
        this.saveGoods(goodsList);
    } 
    
    //获取购物车的总数量
    obj.getTotalCount = function(){
        let goodsList = this.getGoodsList();
        let values = Object.values(goodsList);//Object.values返回的是一个数组,里面对应着每一个key的value
        let sum = 0;
        values.forEach(val => sum = sum +val);
        return sum;
    
    }
    
    export default obj;

      (2)封装好了方法就要在商品详情页面使用(类似于我们在淘宝上买东西,当你在商品详情页面点击加入购物车之后,购物车里面会有对应的商品)

     name:'GoodsDetail',
            data(){
                return{
                    url:`getthumImages/${this.$route.params.id}`,
                    goodsInfo:{},//当前购物车的信息,里面有id
                    pickNum:1 ,
                    isExist:false //让小球默认是隐藏的状态, 
                }
            },
            methods:{
                afterEnter(){
                    this.isExist=false; //显示出来之后执行这个,又将小球隐藏
                    this.$bus.$emit('sendPickNum',this.pickNum);
    
                    //当触发了上面的事件之后,
                    GoodsTool.add({
                        id:this.goodsInfo.id,
                        num:this.pickNum
                    })
                },
                //点击加入购物车执行这个方法,然后让小球显示出来
                ballHandler(){
                    this.isExist=true;
                  //  this.$bus.$emit('sendPickNum',this.pickNum); //将当前的pickNum传过去,但是这个不能加在这里,否者一点击“加入购物车就传
                },
                

      (3)当你一刷新,stroge里面的数据清空,下面的购物车上面的数值又变成0了,所以在下面的底部导航里,让他一开始就获取到当前这个总数

    created(){
        //当你的组件一创建好了后就挂载这个bus公交车,$on这个事件监听
        this.$bus.$on(`sendPickNum`, (data)=>{
          this.pickNum=this.pickNum + data; /
        }),
    
        this.pickNum=GoodsTool.getTotalCount();//直接将这Goods.vue里面传来的数据赋值,
      }

      (4)通过以上思路,就能保证刷新页面时,购物车中的数据不发生改变

    3、点击底部导航“购物车”,将上面加进的东西和数量展示在页面中,(在购物车点击加减按钮,数值做出对应变化)

      (1)首先发送请求,这里发送请求的时候,需要之后再购物详情页面加入的商品的id, 然后根据对应的id拿到对应的请求数据

      (2)拿到购物详情里面的id

    let goodsList = GoodsTool.getGoodsList();//["88":5,"99":4] 第一个数商品id 第二个是商品数量
                let ids = Object.key(goodsList).join(',');//Object.key()获取key值 [88,99]

      (3)拿到上面的id之后就可以发请求

    created(){
                let goodsList = GoodsTool.getGoodsList();//{"88":5,"99":4} 第一个数商品id 第二个是商品数量
                let ids = Object.key(goodsList).join(',');//Object.key()获取key值 [88,99]
                if(ids){
                    this.$axios.get(`goods/getshopcarlist${ids}`)
                    .then(res=>{
                        this.shopCart=res.data.message;
                     
                             }   
                    })
             }

      (4)但是这里的后端数据库里并没有保存加入购物车的数量(如果有可以直接从后端获取),这里手动添加

    created(){
                let goodsList = GoodsTool.getGoodsList();//{"88":5,"99":4} 第一个数商品id 第二个是商品数量
                let ids = Object.key(goodsList).join(',');//Object.key()获取key值 [88,99]
                if(ids){
                    this.$axios.get(`goods/getshopcarlist${ids}`)
                    .then(res=>{
    
                        this.shopCart=res.data.message;//返回的是一个数组
                      //给数组元素添加属性
                      for(var i=0; i<this.shopCart.length;i++){
                          let shop=this.shopCart[i];//获取到当前的对象
                          let num = goodsList[shop.id];//根据当前对象的id查找到对应的购物车数量
    
                            shop.num = num;//给每个对象添加一个num属性,并在视图上渲染,但是会发现视图上的值并没有改变
    
                          }
    
                      }
                    })
                }

      (5)在购物车列表做加减操作,并且将当前的对象传进去

     <li class="p-list" v-for="(shop, index) in shopCart">
                        <mt-switch></mt-switch>
                        <img src="">
                        <div class="pay-calc">
                            <p>{{shop.title}}</p>
                            <div class="calc">
                                <span>¥777</span>
                                <span @click="substract(shop)">-</span>
                                <span>{{shop.num}}</span>
                                <span @click="addNum(shop)">+</span>
                                <a href="javascript:;">删除</a>
                            </div>
                        </div>
                    </li>
    methods:{
                addNum(shop){//每次点击都接受到当前的对象
                    shop.num++; //这里的值虽然加上了,但是,数据并没有响应上去,是因为created是一开始就加载的,后来点击修改了num的值,但是没有 响应视图
                    console.log(shop)
                },
                substract(shop){
                    if(shop.num==1){
                        return;
                    }
    
                    shop.num--;
    
                }
    
            },

      (6)做完第五步,在测试的时候,发现控制台中打印出来的对象中num改变,但是视图上并没有改变

        原因:vue 中存在一种机制会将shopCart(也就是你请求的数据进行监视)属性进行监视,完成响应式(因为后面的num是我们自己加进去的,没有挂载到数据属性里面,vue就会对这个属性进行监视,监视到数据不是完全挂载到数据属性上的,就无法完成响应操作)

                  在vue中的源码中会生成 Object.defineProperty(this, 'shopCart', {   set:function(){   //判断shopCart元素是否有属性  })

        解决方法:如果数据不完整挂载的情况在要添加属性,就需要手动通知vue完成响应式,==》双向数据绑定

    created(){
                let goodsList = GoodsTool.getGoodsList();//{"88":5,"99":4} 第一个数商品id 第二个是商品数量
                let ids = Object.key(goodsList).join(',');//Object.key()获取key值 [88,99]
                if(ids){
                    this.$axios.get(`goods/getshopcarlist${ids}`)
                    .then(res=>{
    
                        this.shopCart=res.data.message;//返回的是一个数组
                      //给数组元素添加属性
                      for(var i=0; i<this.shopCart.length;i++){
                          let shop=this.shopCart[i];//获取到当前的对象
                          let num = goodsList[shop.id];//根据当前对象的id查找到对应的购物车数量
    
                          if(num){
                              shop.num = num;
    
                              this.$set(shop, 'num', num);//自己给这个数据进行双向数据绑定
                              this.$set(shop,'isSelected',true);
                          }
                      }
                    })
                }

    三、总结                                                                             

    踩坑一:自己收动添加的属性,需要用$set()给这个属性绑定

    踩坑二:vue 中存在一种机制会将shopCart(也就是你请求的数据进行监视)属性进行监视,完成响应式(因为后面的num是我们自己加进去的,没有挂载到数据属性里面,vue就会对这个属性进行监视,监视到数据不是完全挂载到数据属性上的,就无法完成响应操作)

    虽然现在走得很慢,但不会一直这么慢
  • 相关阅读:
    angularJS DOM element() $compile()
    windows下python虚拟环境vitrualenv与virtualenvwrapper安装
    django安装 _ django-admin命令_启动服务器命令_创建应用
    Windows下安装phpRedis扩展
    php获取api接口数据的方法
    PHP生成xml数据-XML方式封装接口数据方法
    PHP封装通信接口数据方法-生成json与通信数据标准格式
    PHP之Memcache缓存详解
    jQuery的$.getJSON方法在IE浏览器下失效的解决方案
    好用的日期插件(只需引用即可)
  • 原文地址:https://www.cnblogs.com/xxm980617/p/10706248.html
Copyright © 2011-2022 走看看