1. 项目背景与核心挑战在电商应用开发中订单确认页面是最为复杂的场景之一。它需要整合商品信息、收货地址、优惠券选择、配送时间和支付方式等多种数据同时还要实时计算订单总价。当我们需要将这个功能同时部署到React Native和鸿蒙两个平台时面临的挑战就更加显著。我最近在开发一个跨平台电商应用时就遇到了这样的需求。客户要求订单确认功能在iOS/Android和鸿蒙设备上提供完全一致的用户体验。经过多次迭代我总结出了一套行之有效的方案核心思路是将静态数据商品、地址、优惠券列表与动态选择状态选中优惠券、支付方式、配送时间彻底分离。2. 数据模型设计与状态分离2.1 静态数据模型定义静态数据的特点是初始化后不会改变主要包括商品信息、地址列表和可用优惠券。这些数据通常来自API接口在页面生命周期内保持不变。// 商品项类型 type CartItem { id: string; // 商品项ID productId: string; // 商品ID name: string; // 商品名称 price: number; // 单价 quantity: number; // 数量 color: string; // 选中颜色 size: string; // 选中规格 imageUrl?: string; // 图片URL可选 }; // 地址类型 type Address { id: string; // 地址ID name: string; // 收件人 phone: string; // 电话 address: string; // 详细地址 isDefault: boolean; // 是否默认地址 }; // 优惠券类型 type Coupon { id: string; // 优惠券ID code: string; // 优惠码 name: string; // 名称 discount: number; // 抵扣金额 minAmount: number; // 最低消费 expiryDate: string; // 过期时间 used: boolean; // 是否已使用 };这种设计的关键点在于每个模型都包含了业务所需的完整字段使用TypeScript类型确保数据安全可选字段(imageUrl)增强了灵活性业务规则内置如优惠券的minAmount2.2 动态状态管理动态状态会随着用户操作而变化主要包括// React Native中的状态声明 const [selectedCoupon, setSelectedCoupon] useStatestring | null(null); const [paymentMethod, setPaymentMethod] useStatestring(alipay); const [deliveryTime, setDeliveryTime] useStatestring(尽快送达); // 鸿蒙中的对应实现 State selectedCoupon: string | null null; State paymentMethod: string alipay; State deliveryTime: string 尽快送达;这种分离带来的优势性能优化静态数据不会触发重渲染逻辑清晰业务规则与UI状态解耦易于测试可以单独测试状态逻辑跨平台一致性状态结构完全一致3. 跨平台实现方案3.1 React Native实现要点在RN中我们采用标准的Hooks方案管理状态const OrderConfirmScreen () { // 静态数据使用const声明避免不必要的重渲染 const [cartItems] useStateCartItem[]([...]); const [address] useStateAddress({...}); const [coupons] useStateCoupon[]([...]); // 动态状态 const [selectedCoupon, setSelectedCoupon] useStatestring | null(null); // 其他动态状态... // 价格计算函数 const calculateTotal () { const subtotal cartItems.reduce((sum, item) sum (item.price * item.quantity), 0); const discount selectedCoupon ? coupons.find(c c.id selectedCoupon)?.discount || 0 : 0; return subtotal - discount; }; // 渲染逻辑... }关键优化点使用FlatList优化长列表性能静态数据使用const声明价格计算使用纯函数条件渲染优化如优惠券抵扣行的显示3.2 鸿蒙ArkUI适配方案鸿蒙端需要将React逻辑转换为ArkUI语法但核心数据模型和业务逻辑可以完全复用Entry Component struct OrderConfirmPage { // 静态数据 State cartItems: CartItem[] [...]; State address: Address {...}; State coupons: Coupon[] [...]; // 动态状态 State selectedCoupon: string | null null; // 其他状态... // 价格计算与RN完全一致 calculateTotal(): number { const subtotal this.cartItems.reduce((sum, item) sum (item.price * item.quantity), 0); const discount this.selectedCoupon ? this.coupons.find(c c.id this.selectedCoupon)?.discount || 0 : 0; return subtotal - discount; } // 构建函数 build() { Column() { // 页面结构... } } }适配注意事项使用LazyForEach替代FlatList样式采用链式调用而非StyleSheet交互事件使用onClick而非onPress条件渲染使用if语句而非运算符4. 核心业务逻辑实现4.1 价格计算机制价格计算是订单确认页的核心我们的实现需要保证实时性任何选择变化立即反映在总价上准确性严格遵循业务规则如优惠券使用门槛性能避免不必要的重复计算// 通用计算逻辑RN和鸿蒙完全一致 function calculateTotal( cartItems: CartItem[], coupons: Coupon[], selectedCoupon: string | null ): number { // 商品总价 const subtotal cartItems.reduce((sum, item) sum (item.price * item.quantity), 0); // 优惠券抵扣 let discount 0; if (selectedCoupon) { const coupon coupons.find(c c.id selectedCoupon); if (coupon subtotal coupon.minAmount) { discount coupon.discount; } } // 运费逻辑预留 const shippingFee 0; return subtotal - discount shippingFee; }4.2 选项交互实现对于配送时间、支付方式等选项我们采用统一的交互模式// React Native实现 {[尽快送达, 工作日送货, 周末送货].map(option ( TouchableOpacity key{option} style{[ styles.option, deliveryTime option styles.selectedOption ]} onPress{() setDeliveryTime(option)} Text{option}/Text /TouchableOpacity ))} // 鸿蒙实现 [尽快送达, 工作日送货, 周末送货].forEach(option { Button() .backgroundColor(this.deliveryTime option ? #3b82f6 : #f1f5f9) .onClick(() this.deliveryTime option) .child(Text(option)) })5. 性能优化实践5.1 列表渲染优化对于可能很长的商品列表和优惠券列表我们采用了不同的优化策略React Native:FlatList data{cartItems} renderItem{renderCartItem} keyExtractor{item item.id} initialNumToRender{5} windowSize{10} /鸿蒙:LazyForEach( new MyDataSource(this.cartItems), (item: CartItem) this.renderCartItem(item), (item: CartItem) item.id )5.2 状态更新优化通过分离静态数据和动态状态我们最小化了不必要的重渲染// 好的做法 - 静态数据不会触发重渲染 const [cartItems] useStateCartItem[]([]); // 不好的做法 - 任何变化都会导致重渲染 const [state, setState] useState({ cartItems: [], selectedCoupon: null });6. 样式与布局适配6.1 跨平台样式方案虽然RN使用StyleSheet而鸿蒙使用链式调用但我们可以保持样式结构一致// React Native const styles StyleSheet.create({ card: { backgroundColor: #fff, borderRadius: 12, padding: 16, marginVertical: 8, shadowColor: #000, shadowOpacity: 0.1, shadowRadius: 4, elevation: 2 } }); // 鸿蒙 function cardStyles() { return { backgroundColor: #fff, borderRadius: 12, padding: 16, margin: { top: 8, bottom: 8 }, shadow: { color: #000, opacity: 0.1, radius: 4 } }; }6.2 响应式布局处理对于需要适配不同屏幕尺寸的元素如优惠券卡片我们采用类似的策略// React Native const { width } Dimensions.get(window); const couponWidth (width - 48) / 2 - 8; // 鸿蒙 aboutToAppear() { const windowSize getWindowProperties().windowRect; this.windowWidth windowSize.width; } // 使用时 .width((this.windowWidth - 48) / 2 - 8)7. 踩坑与解决方案在实际开发中我们遇到了几个典型问题问题1鸿蒙LazyForEach的数据源处理最初直接使用数组导致性能问题后来实现了IDataSource接口class MyDataSource implements IDataSource { private list: CartItem[]; private listener: DataChangeListener; constructor(list: CartItem[]) { this.list list; } totalCount(): number { return this.list.length; } getData(index: number): CartItem { return this.list[index]; } // 其他必要方法... }问题2价格计算时机最初在render中直接计算导致不必要的计算改为// 好的做法 - 只在需要时计算 const total useMemo(() calculateTotal(cartItems, coupons, selectedCoupon), [cartItems, coupons, selectedCoupon]);问题3鸿蒙条件渲染语法鸿蒙不支持JSX的语法需要改用if语句// 在build方法中 if (this.selectedCoupon) { // 渲染优惠券抵扣行 }8. 测试策略为确保跨平台一致性我们建立了完善的测试方案数据模型测试验证两个平台的数据结构是否一致计算逻辑测试确保价格计算在所有边界条件下结果一致交互测试验证用户操作后的状态更新是否正确性能测试检查长列表滚动流畅度// 示例测试用例 - 价格计算 describe(calculateTotal, () { it(should apply coupon when meet minAmount, () { const items [{ price: 1000, quantity: 1 }]; const coupons [{ id: 1, discount: 100, minAmount: 500 }]; expect(calculateTotal(items, coupons, 1)).toBe(900); }); it(should not apply coupon when not meet minAmount, () { const items [{ price: 400, quantity: 1 }]; const coupons [{ id: 1, discount: 100, minAmount: 500 }]; expect(calculateTotal(items, coupons, 1)).toBe(400); }); });9. 项目总结与扩展思考通过这个项目我们验证了React Native和鸿蒙在复杂业务场景下实现跨平台一致性的可行性。核心业务逻辑的复用率达到了90%以上主要差异集中在UI层和平台特定API的调用上。对于未来类似项目我会考虑引入状态管理库如Redux/Zustand进一步简化状态共享开发通用的适配层抽象平台差异建立更完善的自动化测试体系探索更多代码共享的可能性如验证逻辑、工具函数等这种架构的另一个优势是便于后续维护。当业务规则变化时如新增优惠券类型我们只需要修改一处核心逻辑两个平台都能受益。