微信小程序实战(商品页面分类实现)

1,240 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

上一篇写了首页商品大类及热门推荐商品展示 ,这一篇开始商品页面分类实现。

image.png

1.页面布局

在分类页面分为两部分,左边部分展示的是大类的信息。而右边的部分则动态展示所选大类的信息以及具体小类下的具体产品信息。这样就有了(大类包含小类,小类包含具体的商品)的关联关系

2.具体表结构设计

1.增加商品小类表(数据见Git源码资源文件夹) 设置:编号、商品小类名称、商品小类、商品大类编号字段 image.png

3.MybatisX插件代码生成

这块就不细说的了具体参考之前的mybatisx 插件的踩坑使用

4.后端代码实现

注意:第1、2步注意增加的字段并非表中的数据,因此需要增加 @TableField(select = false)注解避免报错。

1.将生成的小类实体类增加商品集合并生成set方法让小类中包含具体的商品。

image.png 2.在商品大类中增加商品小类集合

image.png

3.TSmalltypeController增加 获取所有菜单信息接口 接口方法说明:

a.先调用 tBigtypeService.list()方法将产品大类数据查询 b.遍历查到的大类数据同时 调用tSmalltypeService.list(条件)方法根据遍历的大类id与小类表的bigTypeId匹配 c.将查询的小类遍历,将小类id与产品表的typeId字段匹配

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ctsi.sddx.domain.TBigtype;
import com.ctsi.sddx.domain.TProduct;
import com.ctsi.sddx.domain.TSmalltype;
import com.ctsi.sddx.service.TBigtypeService;
import com.ctsi.sddx.service.TProductService;
import com.ctsi.sddx.service.TSmalltypeService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @Author : lizzu
 * @create 2022/10/17 21:23
 */
@RestController
@RequestMapping("v1/miniProgram")
public class TSmalltypeController {

    @Resource
    TBigtypeService tBigtypeService;

    @Resource
    TSmalltypeService tSmalltypeService;

    @Resource
    TProductService tProductService;

    /**
     * 获取所有菜单信息
     * @return
     */
    @GetMapping("tSmalltype/findCategories")
    public List<TBigtype> findCategories(){
        List<TBigtype> tBigtypeList = tBigtypeService.list(); //查询产品大类
        for (TBigtype tBigtype : tBigtypeList) {
            List<TSmalltype> tSmalltypeList = tSmalltypeService.list(new QueryWrapper<TSmalltype>().eq("bigTypeId", tBigtype.getId()));
            tBigtype.setSmallTypeList(tSmalltypeList);
            for (TSmalltype tSmalltype : tSmalltypeList) {
                List<TProduct> tProducts = tProductService.list(new QueryWrapper<TProduct>().eq("typeId", tSmalltype.getId()));
                tSmalltype.setProductList(tProducts);
            }

        }
        return tBigtypeList;
    }

}

接口测试

image.png

5.小程序端代码实现

5.1页面index.wxml

<view class="cates">
  <!-- 搜索框开始 -->
  <SearchBar></SearchBar>
  <!-- 搜索框结束 -->

  <view class="cates_container">
    <!-- 左侧菜单 开始 -->
    <scroll-view class="left_menu" scroll-y>
      <view class="menu_item {{index==0 ? 'active':''}}" wx:for="{{leftMenuList}}" wx:key="*this" data-index="{{index}}">{{item}}</view>
    </scroll-view>
    <!-- 左侧菜单 结束 -->

    <!-- 右侧商品数据 开始 -->
    <scroll-view class="right_container" scroll-y>
      <view class="productType" wx:for="{{rightContent}}" wx:for-item="productType" wx:key="id">
        <view class="productType_title">
          {{productType.name}}
        </view>
        <view class="product_list">
          <navigator wx:for="{{productType.productList}}" wx:key="id" wx:for-item="product">
            <image mode="widthFix" src="{{product.propic}}"></image>
            <view class="right">
              <view class="product_name">{{product.name}}</view>
              <view class="product_price"> ¥ {{product.price}}</view>
            </view>
          </navigator>
        </view>
      </view>
    </scroll-view>
    <!-- 右侧商品数据 结束 -->
  </view>
</view>

5.2 less样式文件(注新建.less文件保存自动生成.wxss代码。具体插件工具见前面章节介绍)

page{
  height: 100%;
}

.cates{
  height: 100%;
  .cates_container{
    height: ~'calc( 100vh - 90rpx )';
    display: flex;
    .left_menu{
      flex:2;
      background-color: aqua;
    }
    .right_container{
      flex:5;
      background-color: blue;
    }
  }
}

5.3效果

image.png

5.4导入SearchBar 公共组件,命名页面标题为:商品分类

{
  "usingComponents": {
    "SearchBar":"/components/SearchBar/SearchBar"
  },
  "navigationBarTitleText": "商品分类"
}

image.png

5.4样式优化

page {
  height: 100%;
}

.cates {
  height: 100%;

  .cates_container {
    height: ~'calc( 100vh - 90rpx )';
    display: flex;

    .left_menu {
      flex: 2;

      .menu_item {
        margin-top: 5rpx;
        height: 80rpx;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 30rpx;
      }

      .active {
        font-weight: bolder;
        color: var(--themeColor);
        border-left: 8rpx solid currentColor;
      }
    }

    .right_container {
      flex: 5;

      .productType {
        padding: 30rpx 20rpx 30rpx 20rpx;
        .productType_title {
          font-weight: bolder;
        }

        .product_list {
          navigator {
            margin: 10rpx;
            display: flex;
            background-color: #F8F8F8;
            image {
              flex: 1;
            }

            .right {
              flex: 3;
              display: flex;
              flex-direction: column;
              justify-content: space-around;
              .product_name {
                padding-top: 10rpx;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
              }

              .product_price {
                padding-bottom: 10rpx;
              }
            }
          }
        }
      }
    }
  }
}

效果:

image.png

5.5 左侧菜单点击切换实现

1.定义当前选中的左侧菜单的索引

image.png

2.依据currentIndex来动态显示被选中菜单的样式:

    <!-- 左侧菜单 开始 -->
    <scroll-view class="left_menu" scroll-y>
      <view class="menu_item {{ index==currentIndex?'active':'' }}"
      wx:for="{{leftMenuList}}"
      wx:key="*this"
      bindtap="handleMenuItemChange"
      data-index="{{index}}">
      {{item}}
      </view>
    </scroll-view>
    <!-- 左侧菜单 结束 -->

3.左侧菜单点击事件handleMenuItemChange

// 左侧菜单的点击事件
  handleMenuItemChange(e) {
    console.log(e)
    const {
      index
    } = e.currentTarget.dataset;
    console.log("index=" + index)
    let rightContent = this.Cates[index].smallTypeList;
    this.setData({
      currentIndex: index,
      rightContent
    })
  },

5.6测试

左侧.gif

5.7设置每次点击左侧菜单右侧菜单位置置顶

思路:页面增加scroll-top 属性每次点击大类方法后设置初始值为0

1.页面增加scroll-top

image.png

2.初始化scrollTop值

  data: {
    leftMenuList: [], // 左侧菜单数据
    rightContent: [], // 右侧商品数据
    // 被点击的左侧的菜单
    currentIndex: 0,
    //右侧菜单滚动条置顶
    scrollTop:0
  },

3.左侧菜单的点击事件后重新设置scrollTop值为0

image.png

5.8 首页商品大类跳转商品分类页面实现

效果描述:点击首页的商品大类跳转到分类页面对应分类的页面。通过wx.switchTab方法,跳转商品分页页面,同时我们需要带参数,但是switchTab方法无法携带参数,所以我们通过全局参数设置的方式,来间接传递参数。

1.增加全局参数用于判断是否首页跳转还是首页商品大类分页点击进来的

// app.js
App({
  onLaunch() {

  },
  globalData: {
    index:-1
  }
})

2.商品大类增加点击事件方法 handleTypeJump 同时传data-index索引。第二行索引加5,因为第二行第一个是从第六个开始排的。

<!-- 商品大类开始 -->
<view class="index_bigType">
  <view class="bigTypeRow">
    <navigator bindtap="handleTypeJump" data-index="{{index}}" 
    wx:for="{{bigTypeList_row1}}" wx:for-item="bigType" wx:key="id">
      <image mode="widthFix" src="{{bigType.image}}"></image>
    </navigator>
  </view>
  <view class="bigTypeRow">
    <navigator bindtap="handleTypeJump" data-index="{{index+5}}" 
     wx:for="{{bigTypeList_row2}}" wx:for-item="bigType" wx:key="id">
      <image mode="widthFix" src="{{bigType.image}}"></image>
    </navigator>
  </view>

</view>
<!-- 商品大类结束 -->
  1. 大类点击事件 通过获取的索引值给全局index参数动态赋值,跳转商品分类页面
  //  大类点击事件
  handleTypeJump(e) {
    const {
      index
    } = e.currentTarget.dataset;
    const app = getApp();
    app.globalData.index = index;
    wx.switchTab({
      url: '/pages/category/index',
    })
  },

5.9 商品分类页面

1.onShow方法上增加 判断是否索引值是否是-1(是-1说明是从底部的分类页点击进来的 如果不是则是首页大类点击跳转过来的) 首页大类点击跳转过来的调用处理getCates2方法并重置index

  onShow() {
    console.log("onShow");
    const app = getApp();
    var index = app.globalData.index;
    console.log("index=" + index)
    if (index != -1) {
      this.getCates2(index);
      app.globalData.index = -1; // 重置index
    }
  },
  1. 处理getCates2()
async getCates2(index) {
    const result = await requestUtil({
      url: '/v1/miniProgram/tSmalltype/findCategories',
      method: "GET"
    });
    this.Cates = result.data;

    let leftMenuList = this.Cates.map(v => v.name)
    let rightContent = this.Cates[index].smallTypeList;
    this.setData({
      leftMenuList,
      rightContent,
      currentIndex: index,
      scrollTop: 0
    })
  },

测试效果:

跳转.gif

至此商品页面分类实现结束

下一篇: 商品详情页面实现