鸿蒙电商购物车全栈实战:用户管理、商品列表与购物车实现
本次实战聚焦于鸿蒙电商购物车全栈项目的核心业务模块,深入讲解用户管理、商品列表及购物车功能的实现逻辑。我们将基于现有架构,完成基础功能的落地,确保数据流转的安全性与界面的响应速度。
一、用户管理基础与架构
用户管理是电商系统的基石,主要涵盖注册、登录、信息维护及权限控制。在架构设计上,我们采用分层模式,将业务逻辑、数据存储、接口设计与界面渲染解耦,便于后期维护与扩展。
- 用户服务层:处理核心业务逻辑;
- 用户数据层:负责数据的持久化存储;
- 用户接口层:定义对外交互标准;
- 用户展示层:负责 UI 渲染与交互反馈。
二、用户管理实战
1. 用户注册实现
注册功能需要处理邮箱验证与密码加密。我们利用单例模式封装工具类,避免重复初始化资源。
entry/src/main/ets/utils/UserRegistrationUtil.ets
import user from '@ohos/user';
// 用户注册工具类
export class UserRegistrationUtil {
private static instance: UserRegistrationUtil | null = null;
private userHelper: user.UserHelper | null = null;
// 单例模式
static getInstance(): UserRegistrationUtil {
if (!UserRegistrationUtil.instance) {
UserRegistrationUtil.instance = new UserRegistrationUtil();
}
return UserRegistrationUtil.instance;
}
// 初始化用户注册
async init(): Promise<void> {
if (!this.userHelper) {
this.userHelper = user.createUserHelper();
}
}
// 用户注册
async register(email: string, password: string): Promise<user.UserRegistrationResult> {
if (!this.userHelper) {
return null;
}
const result = await this.userHelper.register(email, password);
return result;
}
// 发送验证码
async sendVerificationCode(email: string): Promise<user.SendVerificationCodeResult> {
if (!this.userHelper) {
return null;
}
const result = await this.userHelper.sendVerificationCode(email);
return result;
}
}
在页面中,我们通过状态管理绑定输入框,并在点击事件触发工具类方法。注意验证码发送需校验邮箱格式,防止无效请求。
entry/src/main/ets/pages/RegistrationPage.ets
import { UserRegistrationUtil } from '../utils/UserRegistrationUtil';
@Entry
@Component
struct RegistrationPage {
@State email: string = '';
@State password: string = '';
@State verificationCode: string = '';
build() {
Column({ space: 16 }) {
InputComponent({
placeholder: '请输入邮箱',
value: this.email,
onChange: (value: string) => {
this.email = value;
},
type: InputType.Email
});
InputComponent({
placeholder: '请输入密码',
value: this.password,
onChange: (value: string) => {
this.password = value;
},
type: InputType.Password
});
InputComponent({
placeholder: '请输入验证码',
value: this.verificationCode,
onChange: (value: string) => {
this.verificationCode = value;
},
type: InputType.Normal
});
ButtonComponent({
text: '发送验证码',
onClick: async () => {
await this.sendVerificationCode();
},
disabled: !this.email
});
ButtonComponent({
text: '注册',
onClick: async () => {
await this.register();
},
disabled: !this.email || !this.password || !this.verificationCode
});
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#F5F5F5');
}
aboutToAppear() {
// 初始化用户注册
UserRegistrationUtil.getInstance().init();
}
async sendVerificationCode(): Promise<void> {
const result = await UserRegistrationUtil.getInstance().sendVerificationCode(this.email);
if (result.success) {
promptAction.showToast({ message: '验证码发送成功' });
} else {
promptAction.showToast({ message: '验证码发送失败' });
}
}
async register(): Promise<void> {
const result = await UserRegistrationUtil.getInstance().register(this.email, this.password);
if (result.success) {
promptAction.showToast({ message: '注册成功' });
router.pushUrl({ url: '/pages/LoginPage' });
} else {
promptAction.showToast({ message: '注册失败' });
}
}
}
2. 用户登录与信息维护
登录逻辑类似注册,但侧重于身份校验。登录后跳转首页,并支持密码找回。用户信息管理页则允许修改昵称、头像及密码,所有操作均通过工具类异步执行,避免阻塞主线程。
(此处省略部分代码以保持篇幅,实际项目中需完整实现 UserLoginUtil 与 UserInformationManagementUtil)
三、商品列表实战
商品模块需要高效展示数据并提供搜索能力。列表页采用 ListComponent 进行滚动优化,详情页则展示完整信息与购买入口。
1. 商品列表与搜索
entry/src/main/ets/utils/ProductListUtil.ets
import product from '@ohos/product';
export class ProductListUtil {
private static instance: ProductListUtil | null = null;
private productHelper: product.ProductHelper | null = null;
static getInstance(): ProductListUtil {
if (!ProductListUtil.instance) {
ProductListUtil.instance = new ProductListUtil();
}
return ProductListUtil.instance;
}
async init(): Promise<void> {
if (!this.productHelper) {
this.productHelper = product.createProductHelper();
}
}
async getProductList(): Promise<Array<product.Product>> {
if (!this.productHelper) {
return [];
}
const result = await this.productHelper.getProductList();
return result;
}
async searchProduct(keyword: string): Promise<Array<product.Product>> {
if (!this.productHelper) {
return [];
}
const result = await this.productHelper.searchProduct(keyword);
return result;
}
}
页面端通过监听输入框变化触发搜索,同时利用 onItemClick 快速进入详情。
2. 商品详情与加购
详情页不仅展示信息,还集成了数量选择器与加购按钮。这里的关键在于将商品 ID 与数量传递给购物车模块。
entry/src/main/ets/pages/ProductDetailPage.ets
import { ProductDetailUtil } from '../utils/ProductDetailUtil';
import { CartManagementUtil } from '../utils/CartManagementUtil';
@Entry
@Component
struct ProductDetailPage {
@State product: product.Product | null = null;
@State quantity: number = 1;
@State productId: number = 0;
build() {
Column({ space: 16 }) {
if (this.product) {
Image(this.product.avatarUrl)
.width('100%')
.height(240)
.objectFit(ImageFit.Cover)
.borderRadius(8);
Text(this.product.name)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.textColor('#000000');
Text(this.product.description)
.fontSize(14)
.textColor('#666666')
.maxLines(5)
.textOverflow({ overflow: TextOverflow.Ellipsis });
Text(`¥${this.product.price}`)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.textColor('#FF0000');
Row({ space: 16 }) {
Text('数量:').fontSize(14).textColor('#000000');
ButtonComponent({
text: '-',
onClick: () => {
if (this.quantity > 1) {
this.quantity--;
}
},
disabled: this.quantity <= 1
});
Text(`${this.quantity}`).fontSize(14).textColor('#000000');
ButtonComponent({
text: '+',
onClick: () => {
this.quantity++;
},
disabled: this.quantity >= 10
});
}
.width('100%')
.height('auto')
.justifyContent(FlexAlign.Center);
ButtonComponent({
text: '添加到购物车',
onClick: async () => {
await this.addToCart();
},
disabled: !this.product
});
}
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#F5F5F5');
}
aboutToAppear() {
ProductDetailUtil.getInstance().init();
CartManagementUtil.getInstance().init();
this.getProductDetail();
}
async getProductDetail(): Promise<void> {
const params = router.getParams() as { productId: number };
this.productId = params.productId;
this.product = await ProductDetailUtil.getInstance().getProductDetail(this.productId);
}
async addToCart(): Promise<void> {
const result = await CartManagementUtil.getInstance().addToCart(this.productId, this.quantity);
if (result.success) {
promptAction.showToast({ message: '添加到购物车成功' });
} else {
promptAction.showToast({ message: '添加到购物车失败' });
}
}
}
四、购物车管理实战
购物车是交易前的最后一道关卡,需支持数量的实时调整与商品移除。
1. 购物车工具类封装
entry/src/main/ets/utils/CartManagementUtil.ets
import cart from '@ohos/cart';
export class CartManagementUtil {
private static instance: CartManagementUtil | null = null;
private cartHelper: cart.CartHelper | null = null;
static getInstance(): CartManagementUtil {
if (!CartManagementUtil.instance) {
CartManagementUtil.instance = new CartManagementUtil();
}
return CartManagementUtil.instance;
}
async init(): Promise<void> {
if (!this.cartHelper) {
this.cartHelper = cart.createCartHelper();
}
}
async getCartList(): Promise<Array<cart.CartItem>> {
if (!this.cartHelper) {
return [];
}
const result = await this.cartHelper.getCartList();
return result;
}
async addToCart(productId: number, quantity: number): Promise<cart.AddToCartResult> {
if (!this.cartHelper) {
return null;
}
const result = await this.cartHelper.addToCart(productId, quantity);
return result;
}
async modifyCartItemQuantity(cartItemId: number, quantity: number): Promise<cart.ModifyCartItemQuantityResult> {
if (!this.cartHelper) {
return null;
}
const result = await this.cartHelper.modifyCartItemQuantity(cartItemId, quantity);
return result;
}
async deleteCartItem(cartItemId: number): Promise<cart.DeleteCartItemResult> {
if (!this.cartHelper) {
return null;
}
const result = await this.cartHelper.deleteCartItem(cartItemId);
return result;
}
async clearCart(): Promise<cart.ClearCartResult> {
if (!this.cartHelper) {
return null;
}
const result = await this.cartHelper.clearCart();
return result;
}
}
2. 购物车页面交互
entry/src/main/ets/pages/CartPage.ets
import { CartManagementUtil } from '../utils/CartManagementUtil';
@Entry
@Component
struct CartPage {
@State cartList: Array<cart.CartItem> = [];
build() {
Column({ space: 16 }) {
ListComponent({
data: this.cartList,
renderItem: (item: cart.CartItem, index: number) => {
Row({ space: 16 }) {
Image(item.avatarUrl)
.width(80)
.height(80)
.objectFit(ImageFit.Cover)
.borderRadius(8);
Column({ space: 8 }) {
Text(item.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.textColor('#000000');
Text(item.description)
.fontSize(14)
.textColor('#666666')
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis });
Text(`¥${item.price}`)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.textColor('#FF0000');
}
.layoutWeight(1);
Row({ space: 8 }) {
ButtonComponent({
text: '-',
onClick: async () => {
await this.modifyCartItemQuantity(item.cartItemId, item.quantity - 1);
},
disabled: item.quantity <= 1
});
Text(`${item.quantity}`).fontSize(14).textColor('#000000');
ButtonComponent({
text: '+',
onClick: async () => {
await this.modifyCartItemQuantity(item.cartItemId, item.quantity + 1);
},
disabled: item.quantity >= 10
});
}
.width('auto')
.height('auto');
ButtonComponent({
text: '删除',
onClick: async () => {
await this.deleteCartItem(item.cartItemId);
},
disabled: false
});
}
.width('100%')
.height('auto')
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(8)
.margin({ bottom: 8 });
},
onItemClick: (item: cart.CartItem, index: number) => {
router.pushUrl({ url: '/pages/ProductDetailPage', params: { productId: item.productId } });
}
});
ButtonComponent({
text: '清空购物车',
onClick: async () => {
await this.clearCart();
},
disabled: this.cartList.length === 0
});
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#F5F5F5');
}
aboutToAppear() {
CartManagementUtil.getInstance().init();
this.getCartList();
}
async getCartList(): Promise<void> {
this.cartList = await CartManagementUtil.getInstance().getCartList();
}
async modifyCartItemQuantity(cartItemId: number, quantity: number): Promise<void> {
const result = await CartManagementUtil.getInstance().modifyCartItemQuantity(cartItemId, quantity);
if (result.success) {
this.getCartList();
} else {
promptAction.showToast({ message: '修改购物车商品数量失败' });
}
}
async deleteCartItem(cartItemId: number): Promise<void> {
const result = await CartManagementUtil.getInstance().deleteCartItem(cartItemId);
if (result.success) {
this.getCartList();
} else {
promptAction.showToast({ message: '删除购物车商品失败' });
}
}
async clearCart(): Promise<void> {
const result = await CartManagementUtil.getInstance().clearCart();
if (result.success) {
this.getCartList();
} else {
promptAction.showToast({ message: '清空购物车失败' });
}
}
}
五、部署与验证
配置完成后,需在 DevEco Studio 中编译 HAP 包并部署至真机测试。重点验证以下场景:
- 用户注册与登录流程是否顺畅;
- 商品列表加载速度与搜索准确性;
- 购物车数量增减及删除操作的即时性;
- 异常提示(如网络错误)是否友好。
完成上述步骤后,系统已具备完整的电商基础闭环能力,可在此基础上继续拓展订单与支付模块。

