乐优商城(三十二)——购物车

目录

一、搭建购物车微服务

1.1 创建module

1.2 pom依赖

1.3 配置文件

1.4 启动类

二、购物车功能分析

2.1 需求

2.2 流程图

三、未登录购物车

3.1 准备

3.1.1 购物车的数据结构

3.1.2 web本地存储

3.1.3 获取num

3.2 添加购物车

3.2.1 点击事件

3.2.2 获取数量、添加购物车

3.3 查询购物车

3.3.1 校验用户登录

3.3.2 查询购物车

3.3.3 渲染到页面

3.4 修改数量

3.5 删除商品

3.6 选中商品

3.6.1 选中一个

3.6.2 全部选中

3.6.3 初始化全选

3.6.4 总价格

3.6.5 总数量


一、搭建购物车微服务

1.1 创建module

乐优商城(三十二)——购物车_第1张图片

乐优商城(三十二)——购物车_第2张图片

1.2 pom依赖



    
        leyou
        com.leyou.parent
        1.0.0-SNAPSHOT
    
    4.0.0

    com.leyou.cart
    leyou-cart
    1.0.0-SNAPSHOT

    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        
    

1.3 配置文件

server:
  port: 8088
spring:
  application:
    name: cart-service
  redis:
    host: 192.168.19.121
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
    registry-fetch-interval-seconds: 10
  instance:
    instance-id: ${spring.application.name}:${server.port}
    prefer-ip-address: true  #当你获取host时,返回的不是主机名,而是ip
    ip-address: 127.0.0.1
    lease-expiration-duration-in-seconds: 10 #10秒不发送九过期
    lease-renewal-interval-in-seconds: 5 #每隔5秒发一次心跳

1.4 启动类

package com.leyou.cart;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @Author: 98050
 * @Time: 2018-10-24 20:46
 * @Feature:购物车启动器
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class LyCartApplication {

    public static void main(String[] args) {
        SpringApplication.run(LyCartApplication.class,args);
    }
}

二、购物车功能分析

2.1 需求

需求描述:

  • 用户可以在登录状态下将商品添加到购物车

    • 放入数据库

    • 放入redis(采用)

  • 用户可以在未登录状态下将商品添加到购物车

    • 放入localstorage

  • 用户可以使用购物车一起结算下单

  • 用户可以查询自己的购物车

  • 用户可以在购物车中修改购买商品的数量。

  • 用户可以在购物车中删除商品。

  • 在购物车中展示商品优惠信息

  • 提示购物车商品价格变化

2.2 流程图

乐优商城(三十二)——购物车_第3张图片

这幅图主要描述了两个功能:新增商品到购物车、查询购物车。

新增商品:

  • 判断是否登录

    • 是:则添加商品到后台Redis中

    • 否:则添加商品到本地的Localstorage

无论哪种新增,完成后都需要查询购物车列表:

  • 判断是否登录

    • 否:直接查询localstorage中数据并展示

    • 是:已登录,则需要先看本地是否有数据,

      • 有:需要提交到后台添加到redis,合并数据,而后查询

      • 否:直接去后台查询redis,而后返回

三、未登录购物车

3.1 准备

3.1.1 购物车的数据结构

首先分析一下未登录购物车的数据结构。

我们看下页面展示需要什么数据:

乐优商城(三十二)——购物车_第4张图片

因此每一个购物车信息,都是一个对象,包含:

{
    skuId:2131241,
    title:"小米6",
    image:"",
    price:190000,
    num:1,
    ownSpec:"{"机身颜色":"陶瓷黑尊享版","内存":"6GB","机身存储":"128GB"}"
}

另外,购物车中不止一条数据,因此最终会是对象的数组。即:

[
    {...},{...},{...}
]

3.1.2 web本地存储

知道了数据结构,下一个问题,就是如何保存购物车数据。前面分析过,可以使用Localstorage来实现。Localstorage是web本地存储的一种,那么,什么是web本地存储呢?

什么是web本地存储

乐优商城(三十二)——购物车_第5张图片

web本地存储主要有两种方式:

  • LocalStorage:localStorage 方法存储的数据没有时间限制。第二天、第二周或下一年之后,数据依然可用。

  • SessionStorage:sessionStorage 方法针对一个 session 进行数据存储。当用户关闭浏览器窗口后,数据会被删除。

LocalStorage的用法

语法非常简单:

乐优商城(三十二)——购物车_第6张图片

localStorage.setItem("key","value"); // 存储数据
localStorage.getItem("key"); // 获取数据
localStorage.removeItem("key"); // 删除数据

注意:localStorage和SessionStorage都只能保存字符串

不过,在common.js中,已经对localStorage进行了简单的封装:

乐优商城(三十二)——购物车_第7张图片

示例:

乐优商城(三十二)——购物车_第8张图片

3.1.3 获取num

添加购物车需要知道购物的数量,所以需要获取数量大小。在Vue中定义num,保存数量:

乐优商城(三十二)——购物车_第9张图片

然后将num与页面的input框绑定,同时给+-的按钮绑定事件:

编写方法:

乐优商城(三十二)——购物车_第10张图片

3.2 添加购物车

3.2.1 点击事件

商品详情页:

乐优商城(三十二)——购物车_第11张图片

现在点击加入购物车会跳转到购物车成功页面。

不过不这么做,先绑定点击事件,然后实现添加购物车功能。

addCart方法中判断用户的登录状态:

            addCart(){
                ly.http.get("/auth/verify").then(res => {
                    //已经登录发送消息到后台,保存到redis中
                }).catch(() =>{
                    //未登录保存在浏览器本地localStorage中
                })
            }

3.2.2 获取数量、添加购物车

addCart(){
                ly.http.get("/auth/verify").then(res => {
                    //已经登录发送消息到后台,保存到redis中
                }).catch(() =>{
                    //未登录保存在浏览器本地localStorage中
                    //1.查询本地购物车
                    let carts = ly.store.get("carts") || [];
                    let cart = carts.find(c => c.skuId === this.sku.id);
                    //2.判断是否存在
                    if (cart){
                        //3.存在更新数量
                        cart.num += this.num;
                    } else{
                        //4.不存在,新增
                        cart={
                            skuId:this.sku.id,
                            title:this.sku.title,
                            price:this.sku.price,
                            image:this.sku.image,
                            num:this.num,
                            ownSpec:JSON.stringify(this.ownSpec)
                        };
                        carts.push(cart);
                    }
                    //5.把carts写回到localStorage
                    ly.store.set("carts",carts);
                    //6.跳转
                    window.location.href = "http://www.leyou.com/cart.html";
                });
            }

结果:

乐优商城(三十二)——购物车_第12张图片

添加完成后,页面会跳转到购物车结算页面:cart.html

3.3 查询购物车

3.3.1 校验用户登录

因为校验用户会多次进行,所以在common.js中将其封装为一个方法:

乐优商城(三十二)——购物车_第13张图片

然后调用:

乐优商城(三十二)——购物车_第14张图片

3.3.2 查询购物车

页面加载时,就应该去查询购物车。

var cartVm = new Vue({
        el: "#cartApp",
        data: {
            ly,
            carts:[], //购物车数据
        },
        components: {
            shortcut: () => import("/js/pages/shortcut.js")
        },
        created(){
            this.loadCarts();
        },
        methods:{
            loadCarts(){
                //1.先判断登录状态
                ly.verifyUser().then(() => {
                    //2.已经登录
                }).catch(() => {
                    //3.未登陆
                    this.carts = ly.store.get("carts") || [];
                })
            }
        }
    })

刷新页面,查看数据:

乐优商城(三十二)——购物车_第15张图片

3.3.3 渲染到页面

乐优商城(三十二)——购物车_第16张图片

效果:

乐优商城(三十二)——购物车_第17张图片

3.4 修改数量

给页面的 +-绑定点击事件,修改num 的值:

            increment(c){
                c.num++;
                ly.verifyUser().then(() =>{
                    //已经登录,向后台发起请求
                }).catch(() => {
                    //未登录,直接操作本地数据库
                    ly.store.set("carts",this.carts);
                })
            },
            decrement(c){
                if (c.num <= 1){
                    return;
                } 
                c.num--;
                ly.verifyUser().then(() =>{
                    //已经登录,向后台发起请求
                }).catch(() => {
                    //未登录,直接操作本地数据库
                    ly.store.set("carts",this.carts);
                })
            },

3.5 删除商品

给删除按钮绑定事件:

乐优商城(三十二)——购物车_第18张图片

deleteCart(i){
                ly.verifyUser().then(() =>{
                    //已经登录,向后台发起请求
                }).catch(() => {
                    //未登录,直接操作本地数据库
                    this.carts.splice(i,1);
                    ly.store.set("carts",this.carts);
                })
}

3.6 选中商品

在页面中,每个购物车商品左侧,都有一个复选框,用户可以选择部分商品进行下单,而不一定是全部:

乐优商城(三十二)——购物车_第19张图片

定义一个变量,记录所有被选中的商品:

乐优商城(三十二)——购物车_第20张图片

3.6.1 选中一个

给商品前的复选框与selected绑定,并且指定其值为当前购物车商品:

乐优商城(三十二)——购物车_第21张图片

3.6.2 全部选中

分析

乐优商城(三十二)——购物车_第22张图片

页面方法绑定

上:

中:

下:

乐优商城(三十二)——购物车_第23张图片

代码

loadCarts: function () {
                //1.先判断登录状态
                ly.verifyUser().then(() => {
                    //2.已经登录
                }).catch(() => {
                    //3.未登陆
                    this.carts = ly.store.get("carts") || [];
                    this.selected = this.carts;
                    this.$refs.selectAllTop.checked = true;
                    this.$refs.selectAllBottom.checked = true;
                })
            }

初始化是全选的。

            selectAll(){
                if(this.selected.length !== ly.store.get("carts").length){
                    this.selected = this.carts;
                }else  {
                    this.selected = [];
                }
            },
            selectSingle(){

                console.log(this.selected.length);
                console.log(ly.store.get("carts").length);

                if(this.selected.length !== ly.store.get("carts").length - 1){
                    this.$refs.selectAllTop.checked=false;
                    this.$refs.selectAllBottom.checked=false;
                }else{
                    this.$refs.selectAllTop.checked=true;
                    this.$refs.selectAllBottom.checked=true;
                }
            }

注意:为什么要减1?

因为selected和商品选择按钮是双向绑定,当单击按钮时,获取的selected的长度是改变前的长度,所以要进行修正,可自行实验。

3.6.3 初始化全选

加载完成购物车查询后,初始化全选:

乐优商城(三十二)——购物车_第24张图片

3.6.4 总价格

编写计算属性,计算选中商品的总价格:

        computed:{
          totalPrice(){
              return ly.formatPrice(this.selected.reduce((c1,c2) => c1+c2.num*c2.price,0))
          }
        }

乐优商城(三十二)——购物车_第25张图片

3.6.5 总数量

编写计算属性:

totalNum(){
              return this.selected.reduce((c1,c2) => c1+c2.num,0);
          }

乐优商城(三十二)——购物车_第26张图片

效果:

乐优商城(三十二)——购物车_第27张图片

你可能感兴趣的:(乐优商城)