Skip to content
本页目录

4. 分类

4.1 实现分类页面基础结构

  1. 定义页面结构如下:
vue
<template>
	<view>
		<!-- 头部搜索框 -->
		<view class="category-header van-hairline--bottom">
			<navigator class="header-search" url="/subpkg/goods_list/goods_list">
				<icon class="search-icon" type="search" size="13" color="#656771"></icon>
				<text class="search-title">全场50元起步</text>
			</navigator>
		</view>

		<!-- 分类内容 -->
		<view class="search-wrap">
			<!-- 左侧分类菜单 -->
			<scroll-view class="nav-side-wrapper" scroll-y>
				<view class="nav-side">
					<view v-for="item in 10" :key="item">分类1</view>
				</view>
			</scroll-view>
			<!-- 右侧分类内容 -->
			<scroll-view class="search-content" scroll-y>
					<view class="swiper-slide">
						<view class="category-list" v-for="item in 3" :key="item">
							<view class="category-title">标题1</view>
							<view class="product-item" v-for="item in 10" :key="item">
								<image src="//s.weituibao.com/1583591077131/%E5%88%86%E7%B1%BB.png" class="product-img"></image>
								<view class="product-title">分类名</view>
							</view>
						</view>
					</view>
				</block>
			</scroll-view>
		</view>
	</view>
</template>
  1. 美化页面结构
scss
// 搜索头部
.category-header {
	background-color: #fff;
	padding: 14rpx 30rpx;
	color: #656771;
	.header-search {
		display: flex;
		height: 46rpx;
		padding: 10rpx 0;
		background: #f7f7f7;
		border-radius: 40rpx;
		align-items: center;
		justify-content: center;
		font-size: 28rpx;
		.search-icon {
			margin-right: 10rpx;
			color: #656771;
			margin-top: 6rpx;
		}
	}
}

// 分类列表
.search-wrap {
	display: flex;
	justify-content: space-between;
	background-color: #f8f8f8;
	height: calc(100vh - 94rpx);
	overflow: hidden;
	.nav-side-wrapper {
		width: 30%;
		height: 100%;
		.nav-side {
			width: 100%;
			box-sizing: border-box;
			background-color: #f8f8f8;
			.item {
				width: 100%;
				height: 112rpx;
				text-align: center;
				line-height: 112rpx;
				font-size: 28rpx;
				overflow: hidden;
				white-space: nowrap;
				text-overflow: ellipsis;
                // 分类激活样式
				&.active {
					color: $uni-primary;
					background-color: #fff;
				}
			}
		}
	}
	.search-content {
		width: 70%;
		height: 100%;
		padding: 0 20rpx;
		background-color: #fff;
		.swiper-slide {
			width: 100%;
			.category-list {
				display: flex;
				flex-wrap: wrap;
				flex-shrink: 0;
				width: 100%;
				.category-title {
					width: 100%;
					font-size: 30rpx;
					font-weight: 500;
					padding: 40rpx 0;
				}
				.product-item {
					width: 33.3333%;
					margin-bottom: 20rpx;
					text-align: center;
					font-size: 30rpx;
					.product-img {
						width: 60rpx;
						height: 60rpx;
					}
				}
			}
		}
	}
}

4.2 获取分类数据

  1. 定义数据节点

    js
    const state = reactive({
    	categoryData: [],
    	currentIndex: 0
    })
    
  2. 封装数据接口

    js
    import http from '../index.js'
    
    // 获取分类数据
    export function getCategory() {
      return http.get('/categories');
    }
    
  3. 调用获取分类接口

    js
    onMounted(async () => {
    	// 1. 显示加载
    	uni.showLoading({ title: '加载中...', mask: true })
    	// 2. 加载数据
    	const { data } = await getCategory()
    	// 3. 设置数据
    	uni.hideLoading()
    	state.categoryData = data
    	state.currentIndex = data[0].categoryId
    })
    

4.3 动态渲染左侧的一级分类列表

  1. 循环渲染列表结构:

    vue
    <!-- 左侧分类菜单 -->
    <scroll-view class="nav-side-wrapper" scroll-y>
        <view class="nav-side">
            <view v-for="item in categoryData" :class="['item', { active: currentIndex === item.categoryId }]" :key="item.categoryId" >
                {{ item.categoryName }}
            </view>
        </view>
    </scroll-view>
    
  2. 在 data 中定义默认选中项的索引

    js
    const state = reactive({
    	categoryData: [],
    	currentIndex: 0
    })
    
  3. 循环渲染结构时,为选中项动态添加 .active 类名:

    txt
    :class="['item', { active: currentIndex === item.categoryId }]"
    
  4. 为一级分类的 Item 项绑定点击事件处理函数 selectMenu

    txt
    @click="selectMenu(item.categoryId)"
    
  5. 定义 selectMenu 事件处理函数,动态修改选中项的索引:

    js
    // 选择分类
    const selectMenu = index => {
    	state.currentIndex = index
    }
    

4.4 动态渲染右侧的二级分类列表

  1. 循环渲染右侧二级分类列表的 UI 结构:

    vue
    <!-- 右侧分类内容 -->
    <scroll-view class="search-content" scroll-y>
        <block v-for="(category, index) in categoryData"  :key="category.categoryId">
            <view class="swiper-slide" v-if="category.categoryId === currentIndex">
                <view class="category-list" v-for="(products, index2) in category.secondLevelCategoryVOS" :key="products.categoryId">
                    <view class="category-title">{{ products.categoryName }}</view>
                    ...
                </view>
            </view>
        </block>
    </scroll-view>
    

4.5 动态渲染右侧的三级分类列表

  1. 在二级分类的 <view> 组件中,循环渲染三级分类的列表结构:

    vue
    <view class="product-item" v-for="(product, index3) in products.thirdLevelCategoryVOS" :key="product.categoryId" @click="selectProduct(product)">
        <image src="//s.weituibao.com/1583591077131/%E5%88%86%E7%B1%BB.png" class="product-img"></image>
        <view class="product-title">{{ product.categoryName }}</view>
    </view>
    

4.6 切换一级分类后重置滚动条的位置

4.7 点击三级分类跳转到商品列表页面

  1. 为三级分类的 Item 项绑定点击事件处理函数如下:
txt
<view class="product-item" v-for="(product, index3) in products.thirdLevelCategoryVOS" :key="product.categoryId" @click="selectProduct(product)">
  1. 定义事件处理函数如下:
js
// 根据分类选择商品
const selectProduct = item => {
	console.log('item', item.categoryId)
	uni.navigateTo({
		url: `/subpkg/goods_list/goods_list?categoryId=${item.categoryId}`
	})
}