购物车——Tab切换和商品排序

本文介绍了一个购物车案例,涉及商品的综合排序、销量优先、价格排序功能,以及Tab切换来展示母婴、鞋包等不同分类商品。通过Vue.js,JavaScript和HTML实现,数据存储在local Storage,利用Vuex进行状态管理。详细讲解了index.js中的数据获取,Home.vue组件的商品渲染,Tab切换的实现以及商品排序的逻辑。同时,还展示了HTML结构和Style样式的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

效果展示

本篇要做的是个购物车的案例,接下来我们要对购物车中的商品进行综合排序、销量优先、价格从高到低的排序。还有Tab切换,对母婴、鞋包等标签做出相对应的商品展示。这些数据我们可以从后端获取进行使用。

下面是效果图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面代码是储存在local Storage后端的数据,储存名字为goods
在这里插入图片描述

[
//   {
//       "id": 1001,
//       "name": "Beats EP头戴式耳机",
//       "price": 558,
//       "type": 4,
//       "stock": 128,
//       "sales": 1872,
//       "img": "http://img11.360buyimg.com/n1/s528x528_jfs/t3109/194/2435573156/46587/e0e867ac/57e10978N87220944.jpg!q70.jpg"
//   },
//   {


//       "id": 1002,
//       "name": "雀巢(Nestle)高钙成人奶粉",
//       "price": 60,
//       "type": 3,
//       "stock": 5,
//       "sales": 2374,
//       "img": "http://m.360buyimg.com/babel/jfs/t5197/28/400249159/97561/304ce550/58ff0dbeN88884779.jpg!q50.jpg.webp"
//   },
//   {
//       "id": 1003,
//       "name": "煎炒烹炸一锅多用",
//       "price": 216,
//       "type": 5,
//       "stock": 2,
//       "sales": 351,
//       "ishot": true,
//       "img": "http://gw.alicdn.com/tps/TB19OfQRXXXXXbmXXXXL6TaGpXX_760x760q90s150.jpg_.webp"
//   },
//   {
//       "id": 1004,
//       "name": "ANNE KLEIN 潮流经典美式轻奢",
//       "price": 585,
//       "type": 2,
//       "stock": 465,
//       "sales": 8191,
//       "img": "http://gw.alicdn.com/tps/TB1l5psQVXXXXcXaXXXL6TaGpXX_760x760q90s150.jpg_.webp"
//   },
//   {
//       "id": 1005,
//       "name": "乐高EV3机器人积木玩具",
//       "price": 3099,
//       "type": 1,
//       "stock": 154,
//       "sales": 165,
//       "img": "https://m.360buyimg.com/mobilecms/s357x357_jfs/t6490/168/1052550216/653858/9eef28d1/594922a8Nc3afa743.jpg!q50.jpg"
//   },
//   {
//       "id": 1006,
//       "name": "全球购 路易威登(Louis Vuitton)新款女士LV印花手袋 M41112",
//       "price": 10967,
//       "type": 2,
//       "stock": 12,
//       "sales": 6,
//       "img": "https://m.360buyimg.com/n1/s220x220_jfs/t1429/17/1007119837/464370/310392f4/55b5e5bfN75daf703.png!q70.jpg"
//   },
//   {
//       "id": 1007,
//       "name": "Kindle Paperwhite3 黑色经典版电纸书",
//       "price": 805,
//       "type": 4,
//       "stock": 3,
//       "sales": 395,
//       "img": "http://img12.360buyimg.com/n1/s528x528_jfs/t4954/76/635213328/51972/ec4a3c3c/58e5f717N4031d162.jpg!q70.jpg"
//   },
//   {
//       "id": 1008,
//       "name": "DELSEY 男士双肩背包",
//       "price": 269,
//       "type": 2,
//       "stock": 18,
//       "sales": 69,
//       "ishot": true,
//       "img": "http://gw.alicdn.com/tps/LB1HL0mQVXXXXbzXVXXXXXXXXXX.png"
//   },
//   {
//       "id": 1009,
//       "name": "荷兰 天赋力 Herobaby 婴儿配方奶粉 4段 1岁以上700g",
//       "price": 89,
//       "type": 1,
//       "stock": 36,
//       "sales": 1895,
//       "img": "http://m.360buyimg.com/babel/s330x330_jfs/t4597/175/4364374663/125149/4fbbaf21/590d4f5aN0467dc26.jpg!q50.jpg.webp"
//   },
//   {
//       "id": 1010,
//       "name": "【全球购】越南acecook河粉牛肉河粉特产 速食即食方便面粉丝 牛肉河粉米粉65克*5袋",
//       "price": 19.9,
//       "type": 3,
//       "stock": 353,
//       "sales": 3041,
//       "ishot": true,
//       "img": "https://m.360buyimg.com/mobilecms/s357x357_jfs/t3169/228/5426689121/95568/d463e211/586dbf56N37fcd503.jpg!q50.jpg"
//   },
//   {
//       "id": 1011,
//       "name": "正品FENDI/芬迪女包钱包女长款 百搭真皮钱夹 女士小怪兽手拿包",
//       "price": 3580,
//       "type": 2,
//       "stock": 5,
//       "sales": 18,
//       "img": "http://img.alicdn.com/imgextra/i3/TB16avCQXXXXXcsXpXXXXXXXXXX_!!0-item_pic.jpg_400x400q60s30.jpg_.webp"
//   }]

index.js

首先声明一个goodsData数组,在mutations中请求商品列表,在actions中获取后端名为goods的数据放在goodsData数组中并进行提交。提交完之后当然要在我们的组件中进行使用渲染啦。

往下看
在这里插入图片描述

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    goodsData:[],

  },
  mutations: {
    //1.  请求商品列表
    SET_DATA(state,data){
      const {goodsData}=data;
      state.goodsData=goodsData;
     
    },
    
  },
  actions: {
    setData({commit}){
      const goodsData=JSON.parse(localStorage.getItem('goods'))||[];
     
      commit('SET_DATA',{
        goodsData
      })
    },
    
    
  },
  modules: {
  }
})

Home.vue组件

现在,我们vuex中的goodsData有数据了,就可以使用…扩展符获取vuex中的goodsData,并在HTML中v-for渲染显示,记得要想渲染的商品不被刷新掉,就要在生命周期创建后的created中调用vuex中的actions的setData函数

Tab切换

声明一个carType数组用来循环Tab标签并在data中调用。在li标签v-for循环carType,这样Tab按钮就有了。在上面效果图中可以看出Tab切换是点击哪个哪个就有背景颜色,所以绑定名为tab-active的class根据click点击的type进行切换显示商品。因此在computed计算属性中来一个showGoodsData函数,对Tab标签的type进行判断,来过滤筛选,
在这里插入图片描述

商品排序

同样有点击颜色,跟上面的Tab切换一样,只不过排序是根据status的类型进行操作。所以在li中的三个排序分别写入不一样status类型。排序可以在computed计算属性中计算。首先来一个showGoodsData函数,使用switch 来对status的类型进行sort排序,

由于排序中的价格排序有两种,所以要单独写一个方法。首先let声明一个boo默认为true,再在methods中来一个changePrice函数,判断boo的值来对status的类型进行显示或隐藏操作
在这里插入图片描述

import { mapState } from "vuex";

const cartType = [
  {
    name: "推荐",
    type: 0,
  },
  {
    name: "母婴",
    type: 1,
  },
  {
    name: "鞋包饰品",
    type: 2,
  },
  {
    name: "食品",
    type: 3,
  },
  {
    name: "数码家电",
    type: 4,
  },
  {
    name: "居家百货",
    type: 5,
  },
];
let boo = true;
export default {
  data() {
    return {
      cartType,
      type: 0,
      status: "all",
    };
  },

  computed: {
    ...mapState(["goodsData"]),

    showGoodsData() {
      let data = "";
      
      //Tab切换
      if (this.type == 0) {
        data = this.goodsData.map((item) => item);
      } else {
        data = this.goodsData.filter((item) => item.type == this.type);
      }
      
      //商品排序
      switch (this.status) {
        case "all":
          return data;
        case "sales":
          console.log(123);
          return data.sort((a, b) => {
            return b.sales - a.sales;
          });
        case "priceMax":
          return data.sort((a, b) => b.price - a.price);
        case "priceMin":
          return data.sort((a, b) => a.price - b.price);
      }
      return data;
    },
  },

  created() {
    this.$store.dispatch("setData");
  },
  methods: {
    changePrice() {
      if (boo) {
        this.status = "priceMax";
        boo = false;
      } else {
        this.status = "priceMin";
        boo = true;
      }
    },
  },
};

HTML

<template>
  <div class="home">
    <header>
      <span>商品列表</span>
      <router-link to="/About" class="gwc">购物车</router-link>
    </header>

    <div class="flex">
      <ul class="list">
        <li
          class="cate"
          :class="{ 'tab-active': type == item.type }"
          v-for="item in cartType"
          :key="item.id"
          @click="type = item.type"
        >
          {{ item.name }}
        </li>
      </ul>
    </div>

    <ul class="Composite">
      <li
        class="filter-opt price-up"
        :class="{ 'filter-active': status == 'all' }"
        @click="status = 'all'"
      >
        综合排序
      </li>
      <li
        class="filter-opt price-up"
        :class="{ 'filter-active': status == 'sales' }"
        @click="status = 'sales'"
      >
        销量优先
      </li>
      <li
        class="filter-opt filter-price price-up"
        :class="{
          'filter-active': status == 'priceMax' || status == 'priceMin',
        }"
        @click="changePrice"
      >
        价格
      </li>
    </ul>

    <div class="scorll">
      <div class="tj" v-for="item in showGoodsData" :key="item.id">
        <img :src="item.img" alt="" />
        <ul class="xx">
          <li>
            {{ item.name }}
          </li>
          <li><span></span>{{ item.price }}</li>
          <li>{{ item.sales }}付款</li>
        </ul>
        <button class="btn" @click="setCartHandle(item, 'PLUS')">+</button>
      </div>
    </div>
  </div>
</template>

Style样式

<style lang="scss" scoped>
.home {
  header {
    height: 0.3rem;
    display: flex;
    align-items: center;
    justify-content: space-around;
    .gwc {
      position: absolute;
      float: right;
      top: 0;
      right: 20px;
      line-height: 0.3rem;
    }
  }

  .flex {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: pink;
    // 清除滚动条
    .list::-webkit-scrollbar {
      display: none;
    }
    .list {
      // 文本强制不换行
      // white-space: nowrap;
      display: flex;
      overflow-x: scroll;
      li {
        width: 0.8rem;
        height: 53px;
        flex-shrink: 0;
        // display: inline-block;
        line-height: 50px;
        text-align: center;
        padding: 0 7px;
        font-size: 13px;
      }
      .tab-active {
        background-color: white;
      }
    }
  }

  .Composite {
    display: flex;
    align-items: center;
    justify-content: space-around;
    height: 0.3rem;
    color: black;
    border-bottom: solid 1px pink;
  }

  .scorll {
    overflow-y: scroll;
    .tj {
      padding: 10px 0;
      display: flex;
      background: white;
      justify-content: space-around;
      align-items: flex-end;
      margin-bottom: 20px;
      align-items: center;
      box-shadow: 0 2px 10px pink;
      img {
        width: 80px;
        height: 80px;
        float: left;
      }
      .xx {
        width: 2rem;
        text-align: left;
        li:nth-child(1) {
          // 老弹性盒
          display: -webkit-box;
          -webkit-box-orient: vertical;
          // 多行显示  最大两行
          -webkit-line-clamp: 2;
          // 超出文本隐藏
          overflow: hidden;
        }
        li:nth-child(2) {
          color: pink;
          font-weight: 600;
        }
        li {
          margin-top: 5px;
        }
      }
      .btn {
        background: pink;
        text-align: center;
        font-size: 25px;
        font-weight: 700;
        color: white;
        width: 0.2rem;
        border: none;
      }
    }
  }
  .filter-active {
    color: pink;
  }
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值