<think>我们计划开发一个商城分类页面,包含以下核心功能:1.分类侧边栏(左侧)2.商品列表(右侧)3.分类与商品的联动设计思路:-使用Row布局,左侧为分类列表(垂直滚动),右侧为商品网格列表(垂直滚动)-点击分类项时,右侧商品列表自动滚动到对应分类的商品区域-右侧商品列表滚动时,左侧分类项自动高亮当前显示的分类技术要点:1.使用`List`组件实现分类侧边栏2.使用`Grid`或`List`组件实现商品列表3.使用`Scroll`和`Scroller`实现联动滚动4.使用`@State`和`@Link`管理状态数据结构:```typescript//分类interfaceCategory{id:number;name:string;icon:ResourceStr;//图标资源}//商品interfaceProduct{id:number;categoryId:number;name:string;price:number;image:ResourceStr;}```页面结构:```mermaidgraphLRA[分类页面]-->B[左侧分类列表]A-->C[右侧商品列表]B-->B1[分类项1]B-->B2[分类项2]C-->C1[分类1商品网格]C-->C2[分类2商品网格]```代码实现步骤:1.定义分类页面组件结构2.初始化分类和商品数据3.构建左侧分类列表4.构建右侧商品列表(按分类分组)5.实现点击分类滚动到对应商品区域6.实现滚动商品列表时更新左侧选中分类具体实现:</think># 鸿蒙商城分类页面开发指南
## 设计思路与功能规划
基于ArkTS在鸿蒙系统中实现商城分类页面,需要包含以下核心功能:
```mermaid
graph TD
A[分类页面] --> B[顶部导航栏]
A --> C[侧边分类导航]
A --> D[商品网格布局]
A --> E[筛选排序功能]
A --> F[交互反馈机制]
```
## 实现代码
### 1. 定义数据结构
```typescript
// 商品分类
interface Category {
id: number;
name: string;
icon: ResourceStr;
}
// 商品信息
interface Product {
id: number;
name: string;
price: number;
discount?: number; // 折扣率
sales: number; // 销量
stock: number; // 库存
image: ResourceStr;
categoryId: number;
}
// 筛选条件
interface FilterOptions {
sortBy: 'default' | 'priceAsc' | 'priceDesc' | 'sales';
priceRange: [number, number];
onlyInStock: boolean;
}
```
### 2. 分类页面实现
```typescript
@Entry
@Component
struct CategoryPage {
// 分类数据
@State categories: Category[] = [
{ id: 1, name: '手机数码', icon: $r('app.media.category_phone') },
{ id: 2, name: '电脑办公', icon: $r('app.media.category_computer') },
{ id: 3, name: '家用电器', icon: $r('app.media.category_appliance') },
{ id: 4, name: '美妆护肤', icon: $r('app.media.category_beauty') },
{ id: 5, name: '食品生鲜', icon: $r('app.media.category_food') },
{ id: 6, name: '服装鞋包', icon: $r('app.media.category_clothes') },
{ id: 7, name: '母婴玩具', icon: $r('app.media.category_baby') },
{ id: 8, name: '运动户外', icon: $r('app.media.category_sports') },
];
// 商品数据
@State products: Product[] = [
{ id: 101, name: '华为P60 Pro', price: 5988, sales: 2560, stock: 120, image: $r('app.media.product_phone1'), categoryId: 1 },
{ id: 102, name: 'iPhone 15', price: 6999, sales: 1890, stock: 85, image: $r('app.media.product_phone2'), categoryId: 1 },
// 更多商品数据...
];
@State selectedCategoryId: number = 1;
@State filterOptions: FilterOptions = {
sortBy: 'default',
priceRange: [0, 10000],
onlyInStock: false
};
// 筛选后的商品列表
@State filteredProducts: Product[] = [];
aboutToAppear() {
this.filterProducts();
}
// 筛选商品
filterProducts() {
// 1. 按分类筛选
let result = this.products.filter(p => p.categoryId === this.selectedCategoryId);
// 2. 按库存筛选
if (this.filterOptions.onlyInStock) {
result = result.filter(p => p.stock > 0);
}
// 3. 按价格范围筛选
result = result.filter(p =>
p.price >= this.filterOptions.priceRange[0] &&
p.price <= this.filterOptions.priceRange[1]
);
// 4. 排序
switch (this.filterOptions.sortBy) {
case 'priceAsc':
result.sort((a, b) => a.price - b.price);
break;
case 'priceDesc':
result.sort((a, b) => b.price - a.price);
break;
case 'sales':
result.sort((a, b) => b.sales - a.sales);
break;
}
this.filteredProducts = result;
}
// 切换分类
changeCategory(id: number) {
this.selectedCategoryId = id;
this.filterProducts();
}
// 改变排序方式
changeSort(method: 'default' | 'priceAsc' | 'priceDesc' | 'sales') {
this.filterOptions.sortBy = method;
this.filterProducts();
}
// 跳转商品详情
navigateToDetail(productId: number) {
// 实际项目中通过路由跳转
console.log(`跳转到商品详情: ${productId}`);
}
// 商品卡片组件
@Builder
productCard(product: Product) {
Column({ space: 8 }) {
// 商品图片
Stack({ alignContent: Alignment.TopEnd }) {
Image(product.image)
.width('100%')
.aspectRatio(1)
.objectFit(ImageFit.Cover)
.borderRadius(8)
// 折扣标签
if (product.discount) {
Text(`${(product.discount * 100).toFixed(0)}折`)
.fontSize(12)
.fontColor(Color.White)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.backgroundColor('#ff5500')
.borderRadius(4)
.margin(8)
}
}
// 商品名称
Text(product.name)
.fontSize(14)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width('100%')
// 价格区域
Row({ space: 4 }) {
Text(`¥${product.price.toFixed(2)}`)
.fontSize(16)
.fontColor('#ff5500')
.fontWeight(FontWeight.Bold)
if (product.discount) {
Text(`¥${(product.price / product.discount).toFixed(2)}`)
.fontSize(12)
.fontColor('#999')
.decoration({ type: TextDecorationType.LineThrough })
}
}
// 销量和库存
Row({ space: 8 }) {
Text(`销量: ${product.sales}`)
.fontSize(12)
.fontColor('#666')
Text(product.stock > 0 ? '有货' : '缺货')
.fontSize(12)
.fontColor(product.stock > 0 ? '#07c160' : '#ff5500')
}
}
.width('100%')
.padding(8)
.backgroundColor(Color.White)
.borderRadius(12)
.onClick(() => this.navigateToDetail(product.id))
}
// 分类项组件
@Builder
categoryItem(category: Category) {
Column({ space: 8 }) {
Image(category.icon)
.width(40)
.height(40)
Text(category.name)
.fontSize(14)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.padding(12)
.width('100%')
.backgroundColor(this.selectedCategoryId === category.id ? '#fff2e8' : Color.White)
.borderRadius(8)
.onClick(() => this.changeCategory(category.id))
}
// 筛选工具栏
@Builder
filterToolbar() {
Row({ space: 16 }) {
// 综合排序
Button('综合', { type: ButtonType.Capsule })
.stateEffect(this.filterOptions.sortBy === 'default')
.backgroundColor(this.filterOptions.sortBy === 'default' ? '#fff2e8' : '#f5f5f5')
.fontColor(this.filterOptions.sortBy === 'default' ? '#ff5500' : '#333')
.onClick(() => this.changeSort('default'))
// 价格排序
Button('价格', { type: ButtonType.Capsule })
.stateEffect(true)
.backgroundColor(
this.filterOptions.sortBy === 'priceAsc' || this.filterOptions.sortBy === 'priceDesc'
? '#fff2e8' : '#f5f5f5'
)
.fontColor(
this.filterOptions.sortBy === 'priceAsc' || this.filterOptions.sortBy === 'priceDesc'
? '#ff5500' : '#333'
)
.onClick(() => {
if (this.filterOptions.sortBy === 'priceDesc') {
this.changeSort('priceAsc');
} else {
this.changeSort('priceDesc');
}
})
// 销量排序
Button('销量', { type: ButtonType.Capsule })
.stateEffect(this.filterOptions.sortBy === 'sales')
.backgroundColor(this.filterOptions.sortBy === 'sales' ? '#fff2e8' : '#f5f5f5')
.fontColor(this.filterOptions.sortBy === 'sales' ? '#ff5500' : '#333')
.onClick(() => this.changeSort('sales'))
// 筛选按钮
Button('筛选', { type: ButtonType.Capsule })
.backgroundColor('#f5f5f5')
.fontColor('#333')
.onClick(() => {
// 实际项目中打开筛选面板
console.log('打开筛选面板');
})
}
.width('100%')
.padding(12)
.backgroundColor(Color.White)
}
build() {
Row() {
// 左侧分类导航
Scroll() {
Column() {
ForEach(this.categories, (category: Category) => {
this.categoryItem(category)
})
}
.padding(8)
}
.scrollBar(BarState.Off)
.width('25%')
// 右侧商品区域
Column() {
// 筛选工具栏
this.filterToolbar()
// 商品网格
Scroll() {
Grid() {
ForEach(this.filteredProducts, (product: Product) => {
GridItem() {
this.productCard(product)
}
})
}
.columnsTemplate('1fr 1fr')
.columnsGap(8)
.rowsGap(8)
.padding(8)
}
.scrollBar(BarState.Off)
.width('100%')
}
.layoutWeight(1)
.backgroundColor('#f5f5f5')
}
.width('100%')
.height('100%')
.backgroundColor('#f5f5f5')
}
}
```
## 核心技术解析
### 1. 响应式数据管理
- 使用`@State`装饰器管理分类和商品数据状态
- 通过`filterProducts`方法实现数据的动态筛选和排序
- 当分类选择或筛选条件变化时,自动更新商品列表
### 2. 布局设计
- **侧边分类导航**:使用`Scroll`+`Column`实现垂直滚动分类列表
- **商品网格**:使用`Grid`组件实现两列商品展示
- **筛选工具栏**:使用`Row`+`Button`实现水平排列的筛选选项
### 3. ArkTS特性应用
- **@Builder装饰器**:创建可复用的UI组件(`productCard`和`categoryItem`)
- **条件渲染**:根据商品状态显示不同UI元素(折扣标签、库存状态)
- **样式扩展**:使用链式调用设置组件样式
### 4. 交互设计
- **分类选择**:点击分类项高亮显示并刷新商品列表
- **商品点击**:跳转到商品详情页
- **排序切换**:点击排序按钮改变商品排序方式
## 性能优化建议
1. **懒加载优化**:
```typescript
// 使用LazyForEach优化长列表性能
LazyForEach(this.filteredProducts, (product: Product) => {
GridItem() {
this.productCard(product)
}
})
```
2. **图片资源优化**:
```typescript
Image(product.image)
.width('100%')
.aspectRatio(1)
.objectFit(ImageFit.Cover)
.borderRadius(8)
.interpolation(ImageInterpolation.High) // 高质量插值
.renderMode(ImageRenderMode.Original) // 原始质量渲染
```
3. **数据分页加载**:
```typescript
@State currentPage: number = 1;
@State pageSize: number = 20;
loadMoreData() {
// 模拟分页加载
const startIndex = (this.currentPage - 1) * this.pageSize;
const newData = this.allProducts.slice(startIndex, startIndex + this.pageSize);
this.products = [...this.products, ...newData];
this.currentPage++;
}
// 在Scroll组件中添加滚动到底部事件
.onReachEnd(() => {
this.loadMoreData();
})
```
## 相关扩展功能
### 1. 添加搜索功能
```typescript
@State searchKeyword: string = '';
// 在筛选方法中添加搜索条件
if (this.searchKeyword) {
result = result.filter(p =>
p.name.includes(this.searchKeyword)
);
}
// 在顶部添加搜索框
Search({ placeholder: '搜索商品' })
.onChange(value => {
this.searchKeyword = value;
this.filterProducts();
})
```
### 2. 添加购物车快捷操作
```typescript
// 在商品卡片中添加购物车按钮
Button($r('app.media.icon_cart'), { type: ButtonType.Circle })
.width(32)
.height(32)
.position({ x: '85%', y: '85%' })
.onClick(() => {
// 添加到购物车逻辑
})
```
## 相关问题
1. 如何实现分类页面与商品详情页的数据传递?[^1]
2. 如何处理大量分类数据的性能优化问题?
3. 如何在ArkTS中实现自定义的下拉刷新功能?[^2]
4. 如何在不同屏幕尺寸上适配分类页面的布局?[^3]
[^1]: 鸿蒙实战:ArkTs 开发一个鸿蒙应用。ArkTS 通过 struct 声明自定义组件名,使用 @Entry 和 @Component 装饰的自定义组件作为页面的入口。
[^2]: 鸿蒙HarmonyOS开发框架—ArkTS语言(基本语法 一)_鸿蒙 使用 ts。除此之外,ArkTS扩展了多种语法范式来使开发更加便捷。
[^3]: 针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点。