Vue3+TS+移动端-购物车实现详细步骤+项目优化

分析得到:因为购物车,在几个页面都是需要进行数据互通,主页面,商品页面,详情页面,三个不同的组件,要实现一个页面数据变化,另外页面数据跟着变化,那必须要使用vue中vuex,因为是vue3也可以使用pinia

vuex官网:https://vuex.vuejs.org/zh/

pinia官网:https://pinia.web3doc.top/

这次购物车就选用vuex:

第一步:需要配置自动导入

在vite.config.ts中配置

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第1张图片

第二步: 修改store-->index.ts 要实现模块化开发

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第2张图片

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第3张图片

注意:建立好模块之后,index.ts需要引入

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第4张图片

第三步: 配置完成之后,需要重启项目,一定要重新启动

第四步:还需要下载依赖,配置vuex数据持久化存储

vuex的特点是: 全局变量,

他有一个缺点: 如果页面刷新,那我们做的全局变量会初始化

怎么解决这个问题:

用的底层原理就是将 vuex 的全局变量放到 localstorage

localstorage,生命周期,您不删除的话,他不会删除

sessionstorage 生命周期,浏览器关闭了,就会自动删除

官方: 持久化插件

vuex刷新之后他的数据初始化的问题.

用的是持久化插件

下载vuex数据持久化的插件

     npm   i  [email protected] --save

或者 :

    cnpm   i  [email protected] --save

第五步: 配置插件,在index.ts文件中配置,数据持久存储Vue3+TS+移动端-购物车实现详细步骤+项目优化_第5张图片

 完整代码段:

整个代码
import { createStore } from 'vuex'
import cart from "./modules/cart"
import createPersistedState from "vuex-persistedstate";

export default createStore({

  modules: {
    cart
  },
  plugins: [createPersistedState({
    //指定数据被存储在哪里,当值为window.localStorage则表示存储在localStorage中,
    // 当值为window.sessionStorage则表示存储在sessionStorage中
    storage: window.localStorage,
    key: 'sellcard',
    paths: ["cart"]
  })],
})

最后:项目准备工作已经完成了,所有的配置已经完成,接下来就是写代码,实现购物车的业务逻辑

购物车业务逻辑部分:

第一步:在全局变量中定义变量

首先要确定什么类型,是数组,对象,还是字符串,因为是购物车,有很多商品,商品包括名字,价格,数量等.肯定是数组比较合适

 state: {
   // 放全局变量的
   // 定义一个数组存入 你往购物车添加的所有商品
    cartList: []
  },

第二步: 添加购物车的点击事件

添加购物车,需要进行传参,把整个数据传过去

// vue2中store 使用this.$store 因为他是全局挂载
// vue3中store 是按需导入的 不能使用this.$store
// vue3中 let store = new useStore()
// vue3语法糖中 new 不要
// let  store = useStore()
let store = useStore();

//第一个方法是把商品添加到购物车
let addToCart = (food: any) => {
  //这个方法要操作 全局变量
  console.log(food);
  store.commit("setData", food);
};

第三步: 在store的mutations里面设置一个方法

设置这个方法主要是修改改变state中的数据

 mutations: {
        //同步的修改 state的值的方法
        setData(state: any, foodobj: any) {
            // foodobj
            // 没有点餐的数量 要呀
            // 你在点击添加商品的时候.相当于把商品添加进来,然后
            // 数量默认为1
            state.cartList.push({ count: 1, ...foodobj })
        }
    },

第四步: 点击添加购物车案例

小bug出现:点击购物车,跳转到详情页面去了,主要是事件冒泡,需要阻止事件冒泡

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第6张图片

第五步: 实时的更新 商品的状态

主要是解决:有数量的时候显示数据,如果数量为0,显示"添加购物车"

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第7张图片

 v-if和v-else进行判断Vue3+TS+移动端-购物车实现详细步骤+项目优化_第8张图片

 难点:关键是怎么判断,到底什么时候v-if,什么时候v-else呢

问题:

//他不是点击触发出的点击事件
//详情页面也有一个添加购物车
//我点击详情页面的添加购物车,
//商品的按钮就会消失
//因为我已经添加了购物车

解决思路:vue中可以用监听的方式来实时掌握数据源的变化,当数据源发生了变化,就触发这个v-if或者v-else;而且它们返回的true或者false

1.可以用computed实时监听数据源的变化,但是需要传参过去

注意:但是我们需要进行传参,然而计算属性不能传值,用的办法就是返回一个函数,因为函数是可以进行接受传参的,可以解决这个不能传参的问题

 let isHaveFood = computed(() => {
    let fn = (id: any) => {
      //因为v-if最终的结果为true /false
      // 我这里的方法会返回一个true /false
      // 根据数据源的变化而变化
      // 这个数据源在 全局变量中
      // 实时的监听全局变量中的cartList的变化
      //store.getters
      return store.getters.isFood(id);
    };
    return fn;
  });

2.在 getters:中定义,因为getters可以计算数据源的变化情况,但是也是需要返回一个函数,因为计算属性不能传参,返回函数来接收computed传的参数id

// 全局变量中的计算属性
    // 计算属性不能传值,只能返回一个函数才可以传值
    // 主要是判断变量中的id和传过来的id是否相同
    isFood(state: any) {
      return function (id: number) {
        for (let i = 0; i < state.cartList.length; i++) {
          if (state.cartList[i].id == id) {
            return true;
          }
        }
        return false;
      };
    },

3.在getters中实时监听计算state中的数据源,就可以判断是否被添加到购物车了,主要是利用循环,判断每一项,数据源的商品id是否等于computed传过来的id,如果相同就说明添加了购物车,此时就显示数量,否则显示"添加购物车"

第六步: 获取数据,显示数据量,还是添加购物车

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第9张图片

1.在getters定义方法,获取加入购物车的数量

 //得到当前加减数量
    getCount(state: any) {
      return function (id: number) {
        for (let i = 0; i < state.cartList.length; i++) {
          if (state.cartList[i].id == id) {
            return state.cartList[i].count; //返回数量
          }
        }
        return 1;
      };
    },

2.主要还是判断computed计算属性的参数和数据源的id是都相等

  //获取数量
  let getCount = computed(() => {
    return function (id: any) {
      return store.getters.getCount(id);
    };
  });

第七步: 实现加减数量的变化

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第10张图片Vue3+TS+移动端-购物车实现详细步骤+项目优化_第11张图片

 1.给加减号添加点击事件,定义一个方法

 // 给 加减号添加点击事件
+ {{ getCount(ele.id) }} -

 2.编写代码逻辑,但是要注意的是,mutations里面只能接受两个参数,但是我们要传递三个参数,此时用对象

// 在goods.vue中编写方法
// fh 符号  id就是商品的id
let  updCount = (fh,id)=>{
    let obj:Object = {
         fh,
         id
    }
    store.commit("updCount",obj)
}

3.在ts中编写代码

主要是利用循环遍历,state中每一项,判断我们传过去的id和实际数据源中的id是否一样;如果是加号就直接进行数量上相加,主要是当减法的时候,需要再做判断

 // 购物车加减
    updCount(state: any, obj: { fh: string; id: number }) {
      for (let i = 0; i < state.cartList.length; i++) {
        if (state.cartList[i].id == obj.id) {
          if (obj.fh == "+") {
            state.cartList[i].count++;
          } else {
            // 需要判断
            if (state.cartList[i].count > 1) {
              state.cartList[i].count--;
            } else {
              // 如果减到0 将这个商品全局变量中删除 不能在我们购物车中显示了
              state.cartList.splice(i, 1);
              // 如果splice有2个参数的话,表示从i开始,一共删除几个元素
            }
          }
        }
      }
    },

注意:如果数量此时已经不大于1了, 我们就要将这个商品在全局变量中删除,不能在购物车里显示,数组的方法,我们可以用splice,两个参数,第一个代表从i开始,第二个代表删除几个元素.

第八步:购物车弹框显示,已经添加到购物车的商品

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第12张图片

1.在对应vant组件里面找模板,添加购物车,是在我们layout页面进行布局,因为商品组件,也要显示

内容
js中 定义一个变量 // false 代表隐藏 true 代表的是显示 let show = ref(false)

2.我们需要定义一个方法,控制,点击按钮是否显示与隐藏

第九步:显示已选中的商品

问题:怎么去获取state中的值,这里面就是添加购物的商品

1.还是需要用getters来获取

   // 这个是获取购物车中的list中数据
    getCartList(state: any) {
      return state.cartList;
    },

2.用computed计算属性实时监听数据的变化,而且它还有缓存功能

  let getCartList = computed(() => {
    return store.getters.getCartList;
  });

3.页面上显示但是会报错 getCount  updCount 它们在goods.vue写过一次又要用, 复制粘贴过来

页面上使用
 
          
        

最后一步:计算总数量和总价格

1.触发点也是数据源的改变而触发 ,cartList数据改变,他就要触发

    // 总价格和总数量
    getTotal(state: any) {
      let totalNumber: number = 0;
      let totalPrice: number = 0;
      // 循环把数量加起来 数量乘以价格
      for (let i = 0; i < state.cartList.length; i++) {
        totalNumber += state.cartList[i].count;
        totalPrice += state.cartList[i].price * state.cartList[i].count;
      }

      return {
        totalNumber,
        totalPrice: totalPrice * 100, //还需要乘以100方便数据显示
      };
    },
  },


  // 获取总数量和总价格
  let getTotal = computed(() => {
    return store.getters.getTotal;
  });

2.页面上直接渲染即可

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第13张图片

 最后总结:

1.其实里面很多方法,写起来非常的冗余,两个页面重复的代码比较多,这样会造成性能下限,资源浪费,所以我们可以把公共的代码提取出来

2.mixin他的作用就是可以把公共的方法提出来

第一步:

src中新建mixin的目录

第二步:

在mixin的目录中新建一个文件 cartMixin.ts

把公共的方法提出来

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第14张图片

 第三步:完整代码块

export default function () {
  let store = useStore();
  let getCartList = computed(() => {
    return store.getters.getCartList;
  });

  // 获取总数量和总价格
  let getTotal = computed(() => {
    return store.getters.getTotal;
  });

  //第一个方法是把商品添加到购物车
  let addToCart = (food: any) => {
    //这个方法要操作 全局变量
    // console.log(food);
    store.commit("setData", food);
  };

  //他不是点击触发出的点击事件
  //详情页面有一个添加购物车
  //我点击详情页面的添加购物车,
  //商品的按钮就会消失
  //因为我已经添加了购物车
  // 用什么方法去触发这个方法了
  // 计算属性 具有监听的效果
  // 当数据源改变的时候就会触发
  // 计算属性能传值吗?
  // 计算属性在vue中当基本属性使用
  let isHaveFood = computed(() => {
    let fn = (id: any) => {
      //因为v-if最终的结果为true /false
      // 我这里的方法会返回一个true /false
      // 根据数据源的变化而变化
      // 这个数据源在 全局变量中
      // 实时的监听全局变量中的cartList的变化
      //store.getters
      return store.getters.isFood(id);
    };
    return fn;
  });

  //获取数量
  let getCount = computed(() => {
    return function (id: any) {
      return store.getters.getCount(id);
    };
  });

  //加或者减
  //fh符号
  let updCount = (fh: string, id: any) => {
    // 因为加减是点击触发
    // store中mutations去写方法
    //mutations中的方法只有两个参数
    // 第一个参数为state 第二个参数就是你传过去的
    //我们有两个,怎么才能变成一个
    let obj: Object = {
      fh,
      id,
    };
    store.commit("updCount", obj);
  };
  // 把方法暴露出去
  return {
    updCount,
    getCount,
    isHaveFood,
    addToCart,
    getTotal,
    getCartList,
  };
}

第四步:怎么在页面上用,按需引入即可使用

import  cartMixin from "@/mixin/cartMixin.ts"
let { updCount,  getCount, isHaveFood,addToCart,getTotal ,getCartList }  =  cartMixin()
cartMixin是一个方法 用的时候需要添加括号  cartMixin()

cartMixin() 代表的是调用这个方法  这个方法他又返回一个对象

````js

最后的最后:两个页面完整的代码复制在下面:

商品页面完整代码:






Layout页面完整代码:






store下cart.ts完成代码:

export default {
  state: {
    // 全局变量
    cartList: [], //定义一个数组,存你往购物车添加的所有商品
  },
  getters: {
    // 全局变量中的计算属性
    // 计算属性不能传值,只能返回一个函数才可以传值
    // 主要是判断变量中的id和传过来的id是否相同
    isFood(state: any) {
      return function (id: number) {
        for (let i = 0; i < state.cartList.length; i++) {
          if (state.cartList[i].id == id) {
            return true;
          }
        }
        return false;
      };
    },
    //得到当前加减数量
    getCount(state: any) {
      return function (id: number) {
        for (let i = 0; i < state.cartList.length; i++) {
          if (state.cartList[i].id == id) {
            return state.cartList[i].count; //返回数量
          }
        }
        return 1;
      };
    },
    // 这个是获取购物车中的list中数据
    getCartList(state: any) {
      return state.cartList;
    },
    
    // 总价格和总数量
    getTotal(state: any) {
      let totalNumber: number = 0;
      let totalPrice: number = 0;
      // 循环把数量加起来 数量乘以价格
      for (let i = 0; i < state.cartList.length; i++) {
        totalNumber += state.cartList[i].count;
        totalPrice += state.cartList[i].price * state.cartList[i].count;
      }

      return {
        totalNumber,
        totalPrice: totalPrice * 100, //还需要乘以100方便数据显示
      };
    },
  },
  mutations: {
    // 同步的修改state的值的方法
    setData(state: any, foodObj: any) {
      // 要不加的数据追加到变量中
      state.cartList.push({ count: 1, ...foodObj });
    },
    // 购物车加减
    updCount(state: any, obj: { fh: string; id: number }) {
      for (let i = 0; i < state.cartList.length; i++) {
        if (state.cartList[i].id == obj.id) {
          if (obj.fh == "+") {
            state.cartList[i].count++;
          } else {
            // 需要判断
            if (state.cartList[i].count > 1) {
              state.cartList[i].count--;
            } else {
              // 如果减到0 将这个商品全局变量中删除 不能在我们购物车中显示了
              state.cartList.splice(i, 1);
              // 如果splice有2个参数的话,表示从i开始,一共删除几个元素
            }
          }
        }
      }
    },
  },
  actions: {
    // 异步方法 可以修改state
  },
};

样式展示:

Vue3+TS+移动端-购物车实现详细步骤+项目优化_第15张图片

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