鸿蒙电商购物车全栈项目:核心模块实现
本章节聚焦于鸿蒙电商项目的核心业务逻辑,涵盖用户管理、商品展示及购物车流程。我们将基于现有的项目架构,完成基础功能的闭环开发。
一、用户管理基础与架构
用户管理是应用的基础设施,主要包含注册、登录、信息维护及权限控制。在架构设计上,我们采用分层模式:
- 服务层:处理业务逻辑;
- 数据层:负责存储与管理;
- 接口层:定义交互协议;
- 展示层:负责界面渲染。
这种结构有助于解耦,方便后续扩展与维护。
二、用户管理实战
1. 用户注册实现
首先构建注册工具类,采用单例模式确保全局唯一性。
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;
}
}
页面组件中调用上述工具类,并处理 UI 交互:
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. 用户登录与信息维护
登录逻辑类似,重点在于会话保持与错误处理。信息管理页则允许用户更新个人资料和修改密码。
import { UserInformationManagementUtil } from '../utils/UserInformationManagementUtil';
@Entry
@Component
struct UserInformationPage {
@State userInformation: user.UserInformation | null = null;
@State name: string = '';
@State avatarUrl: string = '';
@State oldPassword: string = '';
@State newPassword: string = '';
build() {
Column({ space: 16 }) {
if (this.userInformation) {
Text(`用户 ID:${this.userInformation.userId}`).fontSize(14).textColor('#666666');
}
InputComponent({
placeholder: '请输入姓名',
value: this.name,
onChange: (value: string) => { this.name = value; },
type: InputType.Normal
});
InputComponent({
placeholder: '请输入头像 URL',
value: this.avatarUrl,
onChange: (value: string) => { this.avatarUrl = value; },
type: InputType.Normal
});
ButtonComponent({
text: '修改用户信息',
onClick: async () => { await this.modifyUserInformation(); },
disabled: !this.name || !this.avatarUrl
});
InputComponent({
placeholder: '请输入旧密码',
value: this.oldPassword,
onChange: (value: string) => { this.oldPassword = value; },
type: InputType.Password
});
InputComponent({
placeholder: '请输入新密码',
value: this.newPassword,
onChange: (value: string) => { this.newPassword = value; },
type: InputType.Password
});
ButtonComponent({
text: '修改密码',
onClick: async () => { await this.modifyPassword(); },
disabled: !this.oldPassword || !this.newPassword
});
}.width('100%').height('100%').padding(16).backgroundColor('#F5F5F5');
}
aboutToAppear() {
UserInformationManagementUtil.getInstance().init();
this.getUserInformation();
}
async getUserInformation(): Promise<void> {
this.userInformation = await UserInformationManagementUtil.getInstance().getUserInformation();
this.name = this.userInformation?.name ?? '';
this.avatarUrl = this.userInformation?.avatarUrl ?? '';
}
async modifyUserInformation(): Promise<void> {
const result = await UserInformationManagementUtil.getInstance().modifyUserInformation({
userId: this.userInformation?.userId ?? 0,
name: this.name,
avatarUrl: this.avatarUrl,
email: this.userInformation?.email ?? ''
});
if (result.success) {
promptAction.showToast({ message: '修改用户信息成功' });
this.getUserInformation();
} else {
promptAction.showToast({ message: '修改用户信息失败' });
}
}
async modifyPassword(): Promise<void> {
const result = await UserInformationManagementUtil.getInstance().modifyPassword(this.oldPassword, this.newPassword);
if (result.success) {
promptAction.showToast({ message: '修改密码成功' });
this.oldPassword = '';
this.newPassword = '';
} else {
promptAction.showToast({ message: '修改密码失败' });
}
}
}
三、商品列表与详情
商品模块需要高效展示数据并提供搜索能力。列表页使用 ListComponent 进行滚动渲染,详情页则提供数量选择与加入购物车入口。
import { ProductListUtil } from '../utils/ProductListUtil';
@Entry
@Component
struct ProductListPage {
@State productList: Array<product.Product> = [];
@State searchKeyword: string = '';
build() {
Column({ space: 16 }) {
InputComponent({
placeholder: '请输入搜索关键词',
value: this.searchKeyword,
onChange: (value: string) => { this.searchKeyword = value; },
type: InputType.Normal
});
ButtonComponent({
text: '搜索',
onClick: async () => { await this.searchProduct(); },
disabled: !this.searchKeyword
});
ListComponent({
data: this.productList,
renderItem: (item: product.Product, 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);
ButtonComponent({
text: '查看详情',
onClick: () => {
router.pushUrl({ url: '/pages/ProductDetailPage', params: { productId: item.productId } });
},
disabled: false
});
}.width('100%').height('auto').padding(16).backgroundColor('#FFFFFF').borderRadius(8).margin({ bottom: 8 });
},
onItemClick: (item: product.Product, index: number) => {
router.pushUrl({ url: '/pages/ProductDetailPage', params: { productId: item.productId } });
}
});
}.width('100%').height('100%').padding(16).backgroundColor('#F5F5F5');
}
aboutToAppear() {
ProductListUtil.getInstance().init();
this.getProductList();
}
async getProductList(): Promise<void> {
this.productList = await ProductListUtil.getInstance().getProductList();
}
async searchProduct(): Promise<void> {
this.productList = await ProductListUtil.getInstance().searchProduct(this.searchKeyword);
}
}
四、购物车管理
购物车是电商的核心,需支持增删改查操作。这里通过工具类封装了所有状态变更逻辑,确保数据一致性。
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 中执行编译打包(Build HAP),将生成的包部署至真机或模拟器进行测试。重点验证以下场景:
- 用户注册与登录流程是否顺畅;
- 商品信息加载与搜索响应速度;
- 购物车增减商品后的价格计算与状态同步。
至此,用户体系、商品浏览及购物车核心链路已打通,为后续的订单与支付模块奠定了坚实基础。

