移动开发模式与最佳实践 mobile-development

本技能专注于使用React Native和Flutter进行跨平台移动应用开发,涵盖导航、状态管理和响应式设计等核心模式。适用于构建高效、可扩展的移动应用,提升开发效率和用户体验。关键词:移动开发, React Native, Flutter, 导航, 状态管理, 响应式设计, 跨平台应用, 性能优化, 用户体验

移动开发 0 次安装 0 次浏览 更新于 3/8/2026

name: 移动开发 description: React Native和Flutter的移动开发模式,包括导航、状态管理和响应式设计

移动开发

React Native 组件结构

import { View, Text, FlatList, StyleSheet, Platform } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";

interface Product {
  id: string;
  name: string;
  price: number;
  image: string;
}

function ProductList({ products }: { products: Product[] }) {
  return (
    <SafeAreaView style={styles.container}>
      <FlatList
        data={products}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => <ProductCard product={item} />}
        contentContainerStyle={styles.list}
        ItemSeparatorComponent={() => <View style={styles.separator} />}
        ListEmptyComponent={<EmptyState message="未找到产品" />}
        initialNumToRender={10}
        maxToRenderPerBatch={10}
        windowSize={5}
      />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
  },
  list: {
    padding: 16,
  },
  separator: {
    height: 12,
  },
});

使用 FlatList 用于可滚动列表(永远不要用 ScrollView 结合 .map())。对于大型列表,设置 windowSizemaxToRenderPerBatch

React Native 导航

import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";

type RootStackParams = {
  Tabs: undefined;
  ProductDetail: { productId: string };
  Cart: undefined;
};

const Stack = createNativeStackNavigator<RootStackParams>();
const Tab = createBottomTabNavigator();

function TabNavigator() {
  return (
    <Tab.Navigator screenOptions={{ headerShown: false }}>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Search" component={SearchScreen} />
      <Tab.Screen name="Profile" component={ProfileScreen} />
    </Tab.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Tabs" component={TabNavigator} options={{ headerShown: false }} />
        <Stack.Screen name="ProductDetail" component={ProductDetailScreen} />
        <Stack.Screen name="Cart" component={CartScreen} options={{ presentation: "modal" }} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Flutter 小部件模式

class ProductCard extends StatelessWidget {
  final Product product;
  final VoidCallback onTap;

  const ProductCard({
    super.key,
    required this.product,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Card(
        elevation: 2,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            ClipRRect(
              borderRadius: const BorderRadius.vertical(top: Radius.circular(8)),
              child: Image.network(
                product.imageUrl,
                height: 200,
                width: double.infinity,
                fit: BoxFit.cover,
                errorBuilder: (_, __, ___) => const Icon(Icons.broken_image, size: 64),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(12),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(product.name, style: Theme.of(context).textTheme.titleMedium),
                  const SizedBox(height: 4),
                  Text("\$${product.price.toStringAsFixed(2)}",
                      style: Theme.of(context).textTheme.bodyLarge),
                ],
              ),
            ),
          ],
        ),
      );
    );
  }
}

响应式布局

import { useWindowDimensions } from "react-native";

function useResponsive() {
  const { width } = useWindowDimensions();
  return {
    isPhone: width < 768,
    isTablet: width >= 768 && width < 1024,
    isDesktop: width >= 1024,
    columns: width < 768 ? 1 : width < 1024 ? 2 : 3,
  };
}

function ProductGrid({ products }: { products: Product[] }) {
  const { columns } = useResponsive();

  return (
    <FlatList
      data={products}
      numColumns={columns}
      key={columns}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => (
        <View style={{ flex: 1, maxWidth: `${100 / columns}%`, padding: 8 }}>
          <ProductCard product={item} />
        </View>
      )}
    />
  );
}

平台特定代码

import { Platform } from "react-native";

const styles = StyleSheet.create({
  shadow: Platform.select({
    ios: {
      shadowColor: "#000",
      shadowOffset: { width: 0, height: 2 },
      shadowOpacity: 0.1,
      shadowRadius: 4,
    },
    android: {
      elevation: 4,
    },
    default: {},
  }),
});

反模式

  • 使用 ScrollView 结合 .map() 处理动态列表(应使用 FlatListSectionList
  • 将所有状态存储在全局存储中,而不是与组件共置
  • 未处理安全区域(缺口、状态栏、主页指示器)
  • 每次渲染都使用内联样式(应使用 StyleSheet.create 定义)
  • 用重计算阻塞JS线程(应使用 InteractionManager
  • 忽略平台特定的用户体验约定(iOS的后退滑动、Android的后退按钮)

检查清单

  • [ ] 对所有可滚动列表使用 FlatList,并设置 keyExtractor
  • [ ] 使用TypeScript类型化导航路由参数
  • [ ] 使用 SafeAreaView 处理安全区域插值
  • [ ] 使用 StyleSheet.create 定义样式(而非内联对象)
  • [ ] 响应式布局适配手机、平板和桌面
  • [ ] 使用 Platform.select 处理平台特定样式
  • [ ] 图像缓存并加载错误/加载状态
  • [ ] 将重计算从JS线程卸载