
【跨平台】跨平台开发实战从原生到多端引言跨平台开发一直是移动和桌面应用开发中的热门话题。作为一名有着丰富跨平台开发经验的工程师我使用过PhoneGap、React Native、Flutter等多种跨平台框架也原生开发过iOS和Android应用。每一个框架都有其优势和局限性选择合适的框架需要综合考虑项目需求、团队技术栈、性能要求等多个因素。本文将系统性地介绍跨平台开发的各个方面从React Native到Flutter从桌面Electron到小程序我会结合实际项目经验分析各框架的特点、适用场景和开发实践。同时我也会分享一些跨平台开发中的最佳实践和常见问题的解决方案。一、跨平台开发概述1.1 跨平台框架分类跨平台框架可以分为几大类Web容器型、编译型、混合型以及新兴的AI辅助开发。每种类型都有其特点和适用场景。// 跨平台框架分类 const CrossPlatformFrameworks { // Web容器型基于WebView webContainer: [ Cordova/PhoneGap, Ionic, 微信小程序, 支付宝小程序 ], // 编译型将代码编译为原生代码 compiled: [ Flutter, React Native (Hermes引擎), Kotlin Multiplatform ], // 混合型Web原生 hybrid: [ Capacitor, Electron, Tauri ], // AI辅助开发新兴 aiAssisted: [ Cursor, GitHub Copilot, Claude ] }; // 选择框架的决策树 interface FrameworkSelectionCriteria { performance: high | medium | low; platform: mobile | desktop | all; teamSkill: web | native | mixed; timeToMarket: fast | medium | slow; } function selectFramework(criteria: FrameworkSelectionCriteria): string[] { const recommendations: string[] []; if (criteria.platform mobile) { if (criteria.performance high) { recommendations.push(Flutter); recommendations.push(Kotlin Multiplatform); } else if (criteria.teamSkill web) { recommendations.push(React Native); } } if (criteria.platform desktop) { if (criteria.performance high) { recommendations.push(Tauri); } else { recommendations.push(Electron); } } if (criteria.timeToMarket fast) { recommendations.push(Flutter); recommendations.push(React Native); } return recommendations; }1.2 跨平台架构设计// 跨平台应用架构 interface User { id: string; name: string; email: string; avatar?: string; } interface Order { id: string; userId: string; items: OrderItem[]; totalAmount: number; status: pending | paid | shipped | delivered; createdAt: Date; } interface OrderItem { productId: string; productName: string; quantity: number; price: number; } // 业务逻辑层共享 class OrderService { async createOrder(userId: string, items: OrderItem[]): PromiseOrder { // 验证用户 const user await this.userRepository.findById(userId); if (!user) { throw new Error(User not found); } // 验证库存 for (const item of items) { const available await this.inventoryService.checkStock( item.productId, item.quantity ); if (!available) { throw new Error(Insufficient stock for ${item.productName}); } } // 计算总价 const totalAmount items.reduce( (sum, item) sum item.price * item.quantity, 0 ); // 创建订单 const order: Order { id: this.generateOrderId(), userId, items, totalAmount, status: pending, createdAt: new Date() }; await this.orderRepository.save(order); // 发送通知 await this.notificationService.sendOrderConfirmation(order); return order; } } // 平台特定实现 interface PlatformService { showNotification(title: string, body: string): void; getDeviceInfo(): DeviceInfo; saveToLocalStorage(key: string, value: string): void; } // Flutter实现 class FlutterPlatformService implements PlatformService { showNotification(title: string, body: string): void { // Flutter实现 } getDeviceInfo(): DeviceInfo { return { platform: android, version: 12, deviceId: xxx }; } } // React Native实现 class ReactNativePlatformService implements PlatformService { showNotification(title: string, body: string): void { // React Native实现 } }二、React Native开发2.1 项目结构与配置// 项目结构 /* src/ ├── components/ # 共享组件 │ ├── Button/ │ ├── Input/ │ └── List/ ├── screens/ # 页面 │ ├── HomeScreen/ │ ├── ProfileScreen/ │ └── OrderScreen/ ├── navigation/ # 导航配置 │ ├── AppNavigator.tsx │ └── types.ts ├── services/ # 服务层 │ ├── api/ │ ├── storage/ │ └── analytics/ ├── hooks/ # 自定义Hook │ ├── useAuth.ts │ ├── useOrders.ts │ └── usePlatform.ts ├── store/ # 状态管理 │ └── index.ts ├── utils/ # 工具函数 │ ├── format.ts │ └── validation.ts ├── types/ # 类型定义 │ └── index.ts └── App.tsx */ // React Native导航配置 // navigation/AppNavigator.tsx import React from react; import { NavigationContainer } from react-navigation/native; import { createNativeStackNavigator } from react-navigation/native-stack; import { createBottomTabNavigator } from react-navigation/bottom-tabs; import { GestureHandlerRootView } from react-native-gesture-handler; import { HomeScreen } from ../screens/HomeScreen; import { ProfileScreen } from ../screens/ProfileScreen; import { OrderScreen } from ../screens/OrderScreen; import { LoginScreen } from ../screens/LoginScreen; export type RootStackParamList { Main: undefined; Login: undefined; OrderDetail: { orderId: string }; }; export type MainTabParamList { Home: undefined; Orders: undefined; Profile: undefined; }; const Stack createNativeStackNavigatorRootStackParamList(); const Tab createBottomTabNavigatorMainTabParamList(); const MainTabs () { return ( Tab.Navigator screenOptions{{ tabBarActiveTintColor: #007AFF, tabBarInactiveTintColor: #8E8E93, tabBarStyle: { backgroundColor: #FFFFFF, borderTopColor: #E5E5E5, }, }} Tab.Screen nameHome component{HomeScreen} options{{ title: 首页, tabBarIcon: ({ color }) HomeIcon color{color} /, }} / Tab.Screen nameOrders component{OrderScreen} options{{ title: 订单, tabBarIcon: ({ color }) OrderIcon color{color} /, }} / Tab.Screen nameProfile component{ProfileScreen} options{{ title: 我的, tabBarIcon: ({ color }) ProfileIcon color{color} /, }} / /Tab.Navigator ); }; export const AppNavigator () { const { isAuthenticated } useAuth(); return ( GestureHandlerRootView style{{ flex: 1 }} NavigationContainer Stack.Navigator screenOptions{{ headerStyle: { backgroundColor: #007AFF, }, headerTintColor: #FFFFFF, headerTitleStyle: { fontWeight: bold, }, }} {!isAuthenticated ? ( Stack.Screen nameLogin component{LoginScreen} options{{ headerShown: false }} / ) : ( Stack.Screen nameMain component{MainTabs} options{{ headerShown: false }} / Stack.Screen nameOrderDetail component{OrderDetailScreen} options{{ title: 订单详情 }} / / )} /Stack.Navigator /NavigationContainer /GestureHandlerRootView ); };2.2 原生模块开发// iOS原生模块 // LocalPods/BatteryModule/BatteryModule.swift import UIKit import React objc(BatteryModule) class BatteryModule: NSObject { objc static func requiresMainQueueSetup() - Bool { return true } objc func getBatteryLevel(_ resolve: escaping RCTPromiseResolveBlock, rejecter reject: escaping RCTPromiseRejectBlock) { DispatchQueue.main.async { UIDevice.current.isBatteryMonitoringEnabled true let batteryLevel UIDevice.current.batteryLevel if batteryLevel 0 { resolve([status: unknown, level: -1]) } else { let status self.getBatteryStatus() resolve([status: status, level: batteryLevel * 100]) } } } private func getBatteryStatus() - String { UIDevice.current.isBatteryMonitoringEnabled true switch UIDevice.current.batteryState { case .charging: return charging case .full: return full case .unplugged: return unplugged case .unknown: return unknown unknown default: return unknown } } } // 导出模块到React Native // LocalPods/BatteryModule/BatteryModuleBridge.m #import React/RCTBridgeModule.h interface RCT_EXTERN_MODULE(BatteryModule, NSObject) RCT_EXTERN_METHOD(getBatteryLevel:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) end2.3 性能优化// 性能优化示例 import React, { useCallback, useMemo, memo } from react; import { FlatList, StyleSheet, View, Text, TouchableOpacity, RefreshControl, } from react-native; // 使用React.memo优化列表项 const OrderItem memoOrderItemProps(({ order, onPress }) { const { id, totalAmount, status, createdAt } order; return ( TouchableOpacity style{styles.orderItem} onPress{() onPress(id)} View style{styles.orderHeader} Text style{styles.orderId}订单号: {id}/Text StatusBadge status{status} / /View View style{styles.orderFooter} Text style{styles.orderAmount}¥{totalAmount.toFixed(2)}/Text Text style{styles.orderDate}{formatDate(createdAt)}/Text /View /TouchableOpacity ); }); OrderItem.displayName OrderItem; // 使用useCallback缓存回调 const OrderList: React.FCOrderListProps ({ orders, onOrderPress }) { const [refreshing, setRefreshing] React.useState(false); // 使用useCallback避免不必要重新渲染 const handleRefresh useCallback(() { setRefreshing(true); fetchOrders().finally(() setRefreshing(false)); }, []); const handleOrderPress useCallback((orderId: string) { onOrderPress(orderId); }, [onOrderPress]); // 使用keyExtractor优化列表渲染 const keyExtractor useCallback((item: Order) item.id, []); // 使用getItemLayout优化列表性能 const getItemLayout useCallback( (_: any, index: number) ({ length: 100, offset: 100 * index, index, }), [] ); const renderItem useCallback( ({ item }: { item: Order }) ( OrderItem order{item} onPress{handleOrderPress} / ), [handleOrderPress] ); return ( FlatList data{orders} renderItem{renderItem} keyExtractor{keyExtractor} getItemLayout{getItemLayout} refreshControl{ RefreshControl refreshing{refreshing} onRefresh{handleRefresh} / } initialNumToRender{10} maxToRenderPerBatch{10} windowSize{5} removeClippedSubviews{true} ListEmptyComponent{EmptyState /} contentContainerStyle{styles.listContent} / ); }; // 图片优化 const OptimizedImage: React.FCImageProps memo(({ uri, style }) { const [error, setError] React.useState(false); return ( Image source{{ uri }} style{[styles.image, style]} resizeModecover loadingIndicatorSource{require(./placeholder.png)} progressiveRenderingEnabled{true} fadeDuration{300} onError{() setError(true)} fallback{error} / ); });三、Flutter开发3.1 项目结构与配置// 项目结构 /* lib/ ├── main.dart ├── app.dart ├── core/ # 核心模块 │ ├── constants/ │ │ ├── app_colors.dart │ │ ├── app_strings.dart │ │ └── app_dimensions.dart │ ├── theme/ │ │ ├── app_theme.dart │ │ └── text_styles.dart │ ├── utils/ │ │ ├── extensions.dart │ │ └── validators.dart │ └── errors/ │ └── failures.dart ├── data/ # 数据层 │ ├── models/ │ │ ├── user_model.dart │ │ └── order_model.dart │ ├── repositories/ │ │ ├── user_repository_impl.dart │ │ └── order_repository_impl.dart │ └── datasources/ │ ├── local/ │ └── remote/ ├── domain/ # 领域层 │ ├── entities/ │ │ ├── user.dart │ │ └── order.dart │ ├── repositories/ │ │ ├── user_repository.dart │ │ └── order_repository.dart │ └── usecases/ │ ├── get_user.dart │ └── create_order.dart ├── presentation/ # 表现层 │ ├── blocs/ # BLoC状态管理 │ │ ├── auth/ │ │ ├── order/ │ │ └── user/ │ ├── pages/ │ │ ├── home_page.dart │ │ ├── order_page.dart │ │ └── profile_page.dart │ └── widgets/ │ ├── common/ │ └── custom/ └── di/ # 依赖注入 └── injection.dart */ // pubspec.yaml // name: my_app // description: A cross-platform mobile application // publish_to: none // version: 1.0.01 // environment: // sdk: 3.0.0 4.0.0 // dependencies: // flutter: // sdk: flutter // cupertino_icons: ^1.0.2 // flutter_bloc: ^8.1.0 // get_it: ^7.6.0 // dio: ^5.0.0 // shared_preferences: ^2.2.0 // hive: ^2.2.3 // go_router: ^12.0.0 // json_annotation: ^4.8.0 // equatable: ^2.0.5 // freezed_annotation: ^2.4.0 // dev_dependencies: // flutter_test: // sdk: flutter // flutter_lints: ^3.0.0 // build_runner: ^2.4.0 // json_serializable: ^6.7.0 // freezed: ^2.4.0 // flutter: // uses-material-design: true // assets: // - assets/images/ // - assets/icons/3.2 状态管理BLoC模式// 使用freezed定义不可变状态 // lib/domain/entities/order.dart import package:freezed_annotation/freezed_annotation.dart; part order.freezed.dart; part order.g.dart; freezed class Order with _$Order { const factory Order({ required String id, required String userId, required ListOrderItem items, required double totalAmount, required OrderStatus status, required DateTime createdAt, }) _Order; factory Order.fromJson(MapString, dynamic json) _$OrderFromJson(json); } freezed class OrderItem with _$OrderItem { const factory OrderItem({ required String productId, required String productName, required int quantity, required double price, }) _OrderItem; factory OrderItem.fromJson(MapString, dynamic json) _$OrderItemFromJson(json); } enum OrderStatus { JsonValue(pending) pending, JsonValue(paid) paid, JsonValue(shipped) shipped, JsonValue(delivered) delivered, } // BLoC实现 // lib/presentation/blocs/order/order_event.dart part of order_bloc.dart; abstract class OrderEvent extends Equatable { const OrderEvent(); override ListObject? get props []; } class LoadOrders extends OrderEvent { const LoadOrders(); } class LoadMoreOrders extends OrderEvent { const LoadMoreOrders(); } class CreateOrder extends OrderEvent { final ListCreateOrderItem items; const CreateOrder(this.items); override ListObject? get props [items]; } class RefreshOrders extends OrderEvent { const RefreshOrders(); } // BLoC实现 // lib/presentation/blocs/order/order_state.dart part of order_bloc.dart; freezed class OrderState with _$OrderState { const factory OrderState({ Default([]) ListOrder orders, Default(AsyncValueUnit.loading()) AsyncValueUnit status, Default(false) bool hasReachedMax, String? errorMessage, }) _OrderState; } // lib/presentation/blocs/order/order_bloc.dart import package:flutter_bloc/flutter_bloc.dart; import package:freezed_annotation/freezed_annotation.dart; part order_bloc.freezed.dart; class OrderBloc extends BlocOrderEvent, OrderState { final OrderRepository orderRepository; OrderBloc({required this.orderRepository}) : super(const OrderState()) { onLoadOrders(_onLoadOrders); onLoadMoreOrders(_onLoadMoreOrders); onCreateOrder(_onCreateOrder); onRefreshOrders(_onRefreshOrders); } Futurevoid _onLoadOrders( LoadOrders event, EmitterOrderState emit, ) async { emit(state.copyWith(status: const AsyncValue.loading())); try { final orders await orderRepository.getOrders(page: 1); emit(state.copyWith( orders: orders, status: const AsyncValue.data(Unit), hasReachedMax: orders.isEmpty, )); } catch (e, st) { emit(state.copyWith( status: AsyncValue.error(e, st), errorMessage: e.toString(), )); } } Futurevoid _onLoadMoreOrders( LoadMoreOrders event, EmitterOrderState emit, ) async { if (state.hasReachedMax) return; try { final nextPage (state.orders.length ~/ 10) 1; final newOrders await orderRepository.getOrders(page: nextPage); emit(state.copyWith( orders: [...state.orders, ...newOrders], hasReachedMax: newOrders.isEmpty, )); } catch (e) { emit(state.copyWith(errorMessage: e.toString())); } } Futurevoid _onCreateOrder( CreateOrder event, EmitterOrderState emit, ) async { emit(state.copyWith(status: const AsyncValue.loading())); try { final order await orderRepository.createOrder(event.items); emit(state.copyWith( orders: [order, ...state.orders], status: const AsyncValue.data(Unit), )); } catch (e, st) { emit(state.copyWith( status: AsyncValue.error(e, st), errorMessage: e.toString(), )); } } }3.3 平台通道// Dart端调用原生代码 // lib/services/battery_service.dart import package:flutter/services.dart; class BatteryService { static const MethodChannel _channel MethodChannel(com.example.app/battery); FutureBatteryInfo getBatteryLevel() async { try { final result await _channel.invokeMethodMap(getBatteryLevel); return BatteryInfo.fromMap(result!); } on PlatformException catch (e) { throw Exception(Failed to get battery level: ${e.message}); } } StreamBatteryLevelChange get batteryLevelChanges { return _channel .receiveBroadcastStream() .map((event) BatteryLevelChange.fromMap(event)); } } class BatteryInfo { final String status; final double level; BatteryInfo({required this.status, required this.level}); factory BatteryInfo.fromMap(Mapdynamic, dynamic map) { return BatteryInfo( status: map[status] as String, level: (map[level] as num).toDouble(), ); } } class BatteryLevelChange { final double level; final DateTime timestamp; BatteryLevelChange({required this.level, required this.timestamp}); factory BatteryLevelChange.fromMap(Mapdynamic, dynamic map) { return BatteryLevelChange( level: (map[level] as num).toDouble(), timestamp: DateTime.now(), ); } } // iOS原生实现 // ios/Runner/AppDelegate.swift import Flutter import UIKit main objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) - Bool { let controller window?.rootViewController as! FlutterViewController let batteryChannel FlutterMethodChannel( name: com.example.app/battery, binaryMessenger: controller.binaryMessenger ) batteryChannel.setMethodCallHandler { [weak self] (call, result) in if call.method getBatteryLevel { self?.receiveBatteryLevel(result: result) } else { result(FlutterMethodNotImplemented) } } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } private func receiveBatteryLevel(result: FlutterResult) { let device UIDevice.current device.isBatteryMonitoringEnabled true if device.batteryState .unknown { result(FlutterError( code: UNAVAILABLE, message: Battery level not available, details: nil )) } else { let batteryLevel device.batteryLevel result([ status: self.batteryStatus(device.batteryState), level: batteryLevel * 100 ]) } } private func batteryStatus(_ state: UIDevice.BatteryState) - String { switch state { case .charging: return charging case .full: return full case .unplugged: return unplugged case .unknown: return unknown unknown default: return unknown } } }四、Electron桌面开发4.1 项目配置// electron-builder.json { appId: com.example.app, productName: MyApp, copyright: Copyright © 2024, directories: { output: release/${version}, buildResources: build }, files: [ dist/**/*, package.json ], mac: { category: public.app-category.productivity, hardenedRuntime: true, gatekeeperAssess: false, entitlements: build/entitlements.mac.plist, entitlementsInherit: build/entitlements.mac.plist, target: [ { target: dmg, arch: [x64, arm64] }, { target: zip, arch: [x64, arm64] } ] }, windows: { target: [ { target: nsis, arch: [x64] } ], requestedExecutionLevel: asInvoker }, linux: { target: [AppImage, deb], category: Utility }, nsis: { oneClick: false, allowToChangeInstallationDirectory: true, createDesktopShortcut: true, createStartMenuShortcut: true, shortcutName: MyApp } }4.2 主进程与渲染进程通信// electron/main.ts import { app, BrowserWindow, ipcMain, Menu, Tray, nativeImage } from electron; import * as path from path; import * as fs from fs; let mainWindow: BrowserWindow | null null; let tray: Tray | null null; const isDev process.env.NODE_ENV development; function createWindow(): void { mainWindow new BrowserWindow({ width: 1200, height: 800, minWidth: 800, minHeight: 600, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, preload.js), }, show: false, }); // 加载页面 if (isDev) { mainWindow.loadURL(http://localhost:3000); mainWindow.webContents.openDevTools(); } else { mainWindow.loadFile(path.join(__dirname, ../dist/index.html)); } // 显示窗口 mainWindow.once(ready-to-show, () { mainWindow?.show(); }); // 创建系统菜单 createMenu(); // 创建系统托盘 createTray(); mainWindow.on(closed, () { mainWindow null; }); } // IPC处理器 function setupIpcHandlers(): void { // 文件操作 ipcMain.handle(file:read, async (_, filePath: string) { try { const content await fs.promises.readFile(filePath, utf-8); return { success: true, data: content }; } catch (error) { return { success: false, error: (error as Error).message }; } }); ipcMain.handle(file:write, async (_, filePath: string, content: string) { try { await fs.promises.writeFile(filePath, content, utf-8); return { success: true }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // 系统信息 ipcMain.handle(system:getInfo, () { return { platform: process.platform, arch: process.arch, version: process.getSystemVersion(), electronVersion: process.versions.electron, }; }); // 窗口控制 ipcMain.on(window:minimize, () { mainWindow?.minimize(); }); ipcMain.on(window:maximize, () { if (mainWindow?.isMaximized()) { mainWindow.unmaximize(); } else { mainWindow?.maximize(); } }); ipcMain.on(window:close, () { mainWindow?.close(); }); } // 创建菜单 function createMenu(): void { const template: Electron.MenuItemConstructorOptions[] [ { label: 文件, submenu: [ { label: 新建, accelerator: CmdOrCtrlN, click: () mainWindow?.webContents.send(menu:new), }, { label: 打开, accelerator: CmdOrCtrlO, click: () mainWindow?.webContents.send(menu:open), }, { label: 保存, accelerator: CmdOrCtrlS, click: () mainWindow?.webContents.send(menu:save), }, { type: separator }, { role: quit }, ], }, { label: 编辑, submenu: [ { role: undo }, { role: redo }, { type: separator }, { role: cut }, { role: copy }, { role: paste }, ], }, { label: 视图, submenu: [ { role: reload }, { role: forceReload }, { role: toggleDevTools }, { type: separator }, { role: resetZoom }, { role: zoomIn }, { role: zoomOut }, { type: separator }, { role: togglefullscreen }, ], }, ]; const menu Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); } // 创建托盘 function createTray(): void { const iconPath path.join(__dirname, ../build/icon.png); const icon nativeImage.createFromPath(iconPath); tray new Tray(icon); const contextMenu Menu.buildFromTemplate([ { label: 显示窗口, click: () mainWindow?.show(), }, { label: 关于, click: () mainWindow?.webContents.send(menu:about), }, { type: separator }, { label: 退出, click: () app.quit(), }, ]); tray.setToolTip(MyApp); tray.setContextMenu(contextMenu); tray.on(click, () { mainWindow?.show(); }); } // App生命周期 app.whenReady().then(() { setupIpcHandlers(); createWindow(); app.on(activate, () { if (BrowserWindow.getAllWindows().length 0) { createWindow(); } }); }); app.on(window-all-closed, () { if (process.platform ! darwin) { app.quit(); } });五、微信小程序开发5.1 项目结构// 项目结构 /* miniprogram/ ├── src/ │ ├── app.js # 应用入口 │ ├── app.json # 全局配置 │ ├── app.wxss # 全局样式 │ ├── pages/ # 页面 │ │ ├── index/ # 首页 │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── user/ # 用户页 │ │ └── order/ # 订单页 │ ├── components/ # 组件 │ │ ├── button/ │ │ ├── list/ │ │ └── empty/ │ ├── services/ # 服务 │ │ ├── api.js │ │ ├── auth.js │ │ └── storage.js │ ├── utils/ # 工具 │ │ ├── request.js │ │ └── format.js │ └── constants/ # 常量 │ └── index.js ├── cloudfunctions/ # 云函数 │ ├── login/ │ └── getUserInfo/ ├── sitemap.json └── project.config.json */ // miniprogram/app.json { pages: [ pages/index/index, pages/user/index, pages/order/index, pages/order/detail ], window: { backgroundTextStyle: light, navigationBarBackgroundColor: #007AFF, navigationBarTitleText: 我的应用, navigationBarTextStyle: white }, tabBar: { color: #8E8E93, selectedColor: #007AFF, backgroundColor: #FFFFFF, borderStyle: black, list: [ { pagePath: pages/index/index, text: 首页, iconPath: assets/tabbar/home.png, selectedIconPath: assets/tabbar/home-active.png }, { pagePath: pages/order/index, text: 订单, iconPath: assets/tabbar/order.png, selectedIconPath: assets/tabbar/order-active.png }, { pagePath: pages/user/index, text: 我的, iconPath: assets/tabbar/user.png, selectedIconPath: assets/tabbar/user-active.png } ] }, style: v2, sitemapLocation: sitemap.json }5.2 微信API调用封装// utils/request.js const BASE_URL https://api.example.com; const TOKEN_KEY token; class Request { constructor() { this.baseURL BASE_URL; this.queue new Map(); } request(options) { const { url, method GET, data, header {} } options; const fullURL ${this.baseURL}${url}; return new Promise((resolve, reject) { // 添加token const token wx.getStorageSync(TOKEN_KEY); if (token) { header[Authorization] Bearer ${token}; } // 显示加载提示 if (options.showLoading ! false) { wx.showLoading({ title: 加载中..., mask: true }); } wx.request({ url: fullURL, method, data, header: { Content-Type: application/json, ...header, }, success: (res) { wx.hideLoading(); if (res.statusCode 200) { if (res.data.code 0) { resolve(res.data.data); } else if (res.data.code 401) { // token过期重新登录 this.handleAuthError(); reject(new Error(Unauthorized)); } else { wx.showToast({ title: res.data.message || 请求失败, icon: none, }); reject(new Error(res.data.message)); } } else { this.handleHttpError(res.statusCode); reject(new Error(HTTP Error: ${res.statusCode})); } }, fail: (err) { wx.hideLoading(); wx.showToast({ title: 网络请求失败, icon: none, }); reject(err); }, }); }); } get(url, params, options {}) { let queryString ; if (params) { queryString ? Object.entries(params) .map(([key, value]) ${key}${value}) .join(); } return this.request({ url: url queryString, method: GET, ...options, }); } post(url, data, options {}) { return this.request({ url, method: POST, data, ...options, }); } put(url, data, options {}) { return this.request({ url, method: PUT, data, ...options, }); } delete(url, params, options {}) { let queryString ; if (params) { queryString ? Object.entries(params) .map(([key, value]) ${key}${value}) .join(); } return this.request({ url: url queryString, method: DELETE, ...options, }); } handleAuthError() { wx.removeStorageSync(TOKEN_KEY); wx.navigateTo({ url: /pages/login/index }); } handleHttpError(statusCode) { const errorMessages { 400: 请求参数错误, 403: 拒绝访问, 404: 资源不存在, 500: 服务器错误, 502: 网关错误, 503: 服务不可用, 504: 网关超时, }; wx.showToast({ title: errorMessages[statusCode] || 请求失败, icon: none, }); } } export const request new Request(); // services/api.js export const userAPI { login: (code) request.post(/api/login, { code }), getUserInfo: () request.get(/api/user/info), updateUserInfo: (data) request.put(/api/user/info, data), }; export const orderAPI { getOrders: (params) request.get(/api/orders, params), getOrderDetail: (id) request.get(/api/orders/${id}), createOrder: (data) request.post(/api/orders, data), cancelOrder: (id) request.delete(/api/orders/${id}), };总结跨平台开发是现代应用开发的重要方向。本文系统性地介绍了各种跨平台开发方案React Native适合团队有Web背景使用JavaScript/TypeScriptFlutter适合对性能要求高追求原生体验Electron适合桌面应用开发Web技术栈微信小程序适合国内小程序生态选择跨平台框架的关键考虑因素团队技术栈和经验性能要求目标平台开发周期和成本生态系统支持跨平台开发的核心要点业务逻辑尽量共享平台特定代码最小化建立统一的架构和代码规范注重性能优化和用户体验做好测试确保跨平台一致性希望本文能够帮助大家选择合适的跨平台方案并在实际项目中顺利实现跨平台开发。