跳到主要内容鸿蒙电商购物车全栈实战:用户管理、商品列表与购物车功能实现 | 极客日志TypeScript大前端
鸿蒙电商购物车全栈实战:用户管理、商品列表与购物车功能实现
综述由AI生成鸿蒙电商购物车项目涵盖用户管理、商品列表及购物车核心功能。文章详细讲解了基于 ArkTS 语言的模块化实现方案,包括用户注册登录的单例工具类封装、商品列表的搜索与渲染、以及购物车的增删改查逻辑。通过分层架构设计,确保业务逻辑清晰且易于维护。内容涉及 DevEco Studio 环境配置、HAP 包编译部署及真机调试验证,适合希望快速上手鸿蒙电商应用开发的开发者参考。
不知所云10 浏览 鸿蒙电商购物车全栈实战:用户管理、商品列表与购物车功能实现

在构建鸿蒙电商应用时,用户体系、商品展示与购物车逻辑是核心基础。本文将基于 HarmonyOS 开发环境,深入讲解如何从零搭建用户管理、商品列表及购物车模块,涵盖从架构设计到代码落地的完整流程。
一、用户管理模块设计
用户管理是应用的基石,主要包含注册、登录及个人信息维护。我们采用分层架构来确保业务逻辑清晰:
- 服务层:处理注册、登录等业务逻辑;
- 数据层:负责用户数据的存储与管理;
- 接口层:定义统一的交互接口;
- 展示层:负责界面渲染与用户交互。
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 .;
}
(): <> {
(!.) {
. = user.();
}
}
(: , : ): <user.> {
(!.) ;
result = ..(email, password);
result;
}
(: ): <user.> {
(!.) ;
result = ..(email);
result;
}
}
UserRegistrationUtil
instance
async
init
Promise
void
if
this
userHelper
this
userHelper
createUserHelper
async
register
email
string
password
string
Promise
UserRegistrationResult
if
this
userHelper
return
null
const
await
this
userHelper
register
return
async
sendVerificationCode
email
string
Promise
SendVerificationCodeResult
if
this
userHelper
return
null
const
await
this
userHelper
sendVerificationCode
return
页面实现: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. 用户登录与信息维护
登录流程类似,重点在于状态保持与错误处理。登录后需支持修改密码及更新个人资料。
工具类:entry/src/main/ets/utils/UserLoginUtil.ets
import user from '@ohos.user';
export class UserLoginUtil {
private static instance: UserLoginUtil | null = null;
private userHelper: user.UserHelper | null = null;
static getInstance(): UserLoginUtil {
if (!UserLoginUtil.instance) {
UserLoginUtil.instance = new UserLoginUtil();
}
return UserLoginUtil.instance;
}
async init(): Promise<void> {
if (!this.userHelper) {
this.userHelper = user.createUserHelper();
}
}
async login(email: string, password: string): Promise<user.UserLoginResult> {
if (!this.userHelper) return null;
const result = await this.userHelper.login(email, password);
return result;
}
async forgetPassword(email: string): Promise<user.ForgetPasswordResult> {
if (!this.userHelper) return null;
const result = await this.userHelper.forgetPassword(email);
return result;
}
}
页面实现:entry/src/main/ets/pages/LoginPage.ets
import { UserLoginUtil } from '../utils/UserLoginUtil';
@Entry
@Component
struct LoginPage {
@State email: string = '';
@State password: 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
});
ButtonComponent({
text: '登录',
onClick: async () => { await this.login(); },
disabled: !this.email || !this.password
});
Text('忘记密码')
.fontSize(14)
.textColor('#666666')
.onClick(() => { this.forgetPassword(); });
}.width('100%').height('100%').padding(16).backgroundColor('#F5F5F5');
}
aboutToAppear() {
UserLoginUtil.getInstance().init();
}
async login(): Promise<void> {
const result = await UserLoginUtil.getInstance().login(this.email, this.password);
if (result.success) {
promptAction.showToast({ message: '登录成功' });
router.pushUrl({ url: '/pages/HomePage' });
} else {
promptAction.showToast({ message: '登录失败' });
}
}
async forgetPassword(): Promise<void> {
const result = await UserLoginUtil.getInstance().forgetPassword(this.email);
if (result.success) {
promptAction.showToast({ message: '密码重置邮件已发送' });
} else {
promptAction.showToast({ message: '密码重置邮件发送失败' });
}
}
}
用户信息管理页 entry/src/main/ets/pages/UserInformationPage.ets 允许用户更新头像、昵称及修改密码,逻辑上复用上述工具类进行数据持久化。
二、商品列表与详情
商品模块的核心在于高效展示与搜索。通过 ProductListUtil 封装数据获取逻辑,前端组件负责渲染。
1. 商品列表页
列表页需支持分页加载与关键词搜索。使用 ListComponent 优化长列表性能。
工具类: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;
}
}
页面实现:entry/src/main/ets/pages/ProductListPage.ets
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);
}
}
2. 商品详情页
详情页不仅展示信息,还需集成'加入购物车'操作。注意数量选择器的边界控制。
工具类:entry/src/main/ets/utils/ProductDetailUtil.ets
import product from '@ohos.product';
export class ProductDetailUtil {
private static instance: ProductDetailUtil | null = null;
private productHelper: product.ProductHelper | null = null;
static getInstance(): ProductDetailUtil {
if (!ProductDetailUtil.instance) {
ProductDetailUtil.instance = new ProductDetailUtil();
}
return ProductDetailUtil.instance;
}
async init(): Promise<void> {
if (!this.productHelper) {
this.productHelper = product.createProductHelper();
}
}
async getProductDetail(productId: number): Promise<product.Product> {
if (!this.productHelper) return null;
const result = await this.productHelper.getProductDetail(productId);
return result;
}
async addToCart(productId: number, quantity: number): Promise<product.AddToCartResult> {
if (!this.productHelper) return null;
const result = await this.productHelper.addToCart(productId, quantity);
return result;
}
}
页面实现: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: '添加到购物车失败' });
}
}
}
三、购物车管理实战
购物车是电商转化的关键节点,需支持增删改查及总价计算(此处简化为数量调整)。
工具类: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;
}
}
页面实现: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 中进行编译打包。点击 Build → Build HAP 生成安装包,随后连接真机或模拟器进行调试。
- 注册登录流程的异常处理(如网络中断);
- 商品列表的加载速度与搜索响应;
- 购物车数量的增减是否实时更新;
- 数据持久化是否生效。
通过上述步骤,我们完成了鸿蒙电商应用中用户、商品与购物车三大核心模块的开发。后续可在此基础上扩展订单支付、会员体系等功能。
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online