基本页面路径
my-app/
├─ android/ # Android 原生代码
├─ ios/ # iOS 原生代码
├─ src/ # 主业务源码
│ ├─ assets/ # 图片、字体、icon、静态资源
│ │ ├─ images/
│ │ ├─ fonts/
│ │ └─ icons/
│ ├─ components/ # 可复用组件(UI组件)
│ │ ├─ Button/
│ │ ├─ Input/
│ │ └─ TabBar/
│ ├─ pages/ # 页面(按模块拆分)
│ │ ├─ Home/
│ │ │ ├─ index.tsx
│ │ │ ├─ styles.ts
│ │ │ └─ components/ # 页面级私有组件
│ │ ├─ User/
│ │ └─ Detail/
│ ├─ router/ # 路由
│ │ ├─ RootNavigator.tsx # Stack + Tab 主入口
│ │ ├─ TabNavigator.tsx # TabBar 页面
│ │ └─ types.ts # 路由类型 TS
│ ├─ store/ # 全局状态管理
│ │ ├─ index.ts # store 总入口
│ │ ├─ user.ts # 用户状态
│ │ └─ home.ts # 首页状态
│ ├─ services/ # 网络请求 / API
│ │ ├─ index.ts # axios / fetch 封装
│ │ ├─ userApi.ts
│ │ └─ productApi.ts
│ ├─ hooks/ # 自定义 hooks
│ │ ├─ useAuth.ts
│ │ └─ useFetch.ts
│ ├─ utils/ # 工具函数
│ │ ├─ format.ts
│ │ └─ storage.ts # MMKV/AsyncStorage 封装
│ ├─ constants/ # 常量
│ │ ├─ colors.ts
│ │ ├─ strings.ts
│ │ └─ configs.ts
│ └─ App.tsx # 应用入口
├─ index.js # RN入口文件
├─ package.json
├─ tsconfig.json
├─ metro.config.js # RN打包配置
└─ babel.config.js
目录设计原则
- 按功能模块拆分
- pages → 按业务模块(Home、User、Detail)
- components → 公共可复用组件(Button、Input、TabBar)
- 路由集中管理
- navigation 下统一管理 Stack + Tab,方便多人协作
- types.ts 用 TS 类型保证路由跳转安全
- 状态管理集中
- store 下按模块拆分
- 每个模块对应自己的状态文件,后期可扩展为 Redux / Zustand / Jotai
- 服务层统一管理 API
- services 下按功能拆分
- 全局 axios / fetch 封装,方便统一拦截请求、token刷新
- hooks + utils
- hooks → 自定义 hook(业务逻辑复用)
- utils → 工具函数(format、storage、debounce 等)
- assets 独立静态资源
- 图片、字体、icon 分类,避免杂乱
- 可配合 react-native-svg 或 @expo/vector-icons
路由常用插件
npm install @react-navigation/native @react-navigation/bottom-tabs @react-navigation/native-stack
npm install react-native-screens react-native-safe-area-context
基础配置 如tabbar页面 子页面
-
src/navigation/TabNavigator.tsx 👉 4个TabBar
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import HomeScreen from "../screens/HomeScreen";
import CategoryScreen from "../screens/CategoryScreen";
import CartScreen from "../screens/CartScreen";
import ProfileScreen from "../screens/ProfileScreen";const Tab = createBottomTabNavigator();
export default function TabNavigator() {
return (
<Tab.Navigator screenOptions={{ headerShown:false, tabBarActiveTintColor:"#0094FF" }}>
<Tab.Screen name="Home" component={HomeScreen} options={{ title:"首页" }}/>
<Tab.Screen name="Category" component={CategoryScreen} options={{ title:"分类" }}/>
<Tab.Screen name="Cart" component={CartScreen} options={{ title:"购物车" }}/>
<Tab.Screen name="Profile" component={ProfileScreen} options={{ title:"我的" }}/>
</Tab.Navigator>
);
} -
src/navigation/StackNavigator.tsx 👉 包含一个子页面
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import TabNavigator from "./TabNavigator";
import DetailScreen from "../screens/DetailScreen";const Stack = createNativeStackNavigator();
export default function StackNavigator() {
return (
<Stack.Navigator>
<Stack.Screen name="Tabs" component={TabNavigator} options={{ headerShown:false }}/>
<Stack.Screen name="Detail" component={DetailScreen} options={{ title:"商品详情" }}/>
</Stack.Navigator>
);
} -
入口 --- App.tsx
import { NavigationContainer } from "@react-navigation/native";
import StackNavigator from "./src/navigation/StackNavigator";export default function App() {
return (
<NavigationContainer>
<StackNavigator/>
</NavigationContainer>
);
} -
子页面跳转方式
import { useNavigation } from "@react-navigation/native";
export default function HomeScreen(){
const navigation = useNavigation();return (
<Button
title="进入详情页"
onPress={() => navigation.navigate("Detail",{ id:1001 })}
/>
);
}
<Button title="Go to Detail" onPress={()=>navigation.navigate('Detail',{id:"1545"})}/>类型报错 类型"[string, { id: string; }]"的参数不能赋给类型"never"的参数
类型报错解决方案
-
定义路由类型 types.ts
export type RootStackParamList = {
Tabs: undefined;
Detail: { id: string }; // 🌟 这里定义参数 id 为 string
}; -
修改 StackNavigator.tsx 绑定类型
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { RootStackParamList } from "./types";
import TabNavigator from "./TabNavigator";
import DetailScreen from "../screens/DetailScreen";const Stack = createNativeStackNavigator<RootStackParamList>(); // ★ 类型加上
export default function StackNavigator() {
return (
<Stack.Navigator>
<Stack.Screen name="Tabs" component={TabNavigator} options={{ headerShown: false }} />
<Stack.Screen name="Detail" component={DetailScreen} />
</Stack.Navigator>
);
} -
页面跳转(你的Button报错的地方)
import { useNavigation } from "@react-navigation/native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { RootStackParamList } from "../navigation/types";type Nav = NativeStackNavigationProp<RootStackParamList, 'Detail'>;
export default function HomeScreen() {
const navigation = useNavigationreturn (
<Button
title="Go to Detail"
onPress={() => navigation.navigate("Detail", { id: "1545" })} // ✔ 现在不会报错
/>
);
} -
获取参数 DetailScreen.tsx
import { RouteProp, useRoute } from "@react-navigation/native";
import { RootStackParamList } from "../navigation/types";type DetailRoute = RouteProp<RootStackParamList, 'Detail'>;
export default function DetailScreen(){
const { id } = useRoute<DetailRoute>().params;return <Text>商品ID: {id}</Text>;
}
页面适配方案
安装插件
npm i react-native-size-matters react-native-responsive-screen
创建适配工具
import { scale, verticalScale, moderateScale } from "react-native-size-matters";
import { widthPercentageToDP, heightPercentageToDP } from "react-native-responsive-screen";
export const s = scale; // 等比缩放 → UI宽度适配
export const vs = verticalScale; // 高度缩放
export const ms = moderateScale; // 缩放带衰减,字体更舒服
export const wp = widthPercentageToDP; // 相对屏幕宽度百分比
export const hp = heightPercentageToDP; // 相对屏高百分比
页面使用方法
import { View, Text, StyleSheet } from "react-native";
import { s, vs, ms, wp } from "../utils/scale";
export default function Demo() {
return (
<View style={{ padding: s(20) }}>
<Text style={{ fontSize: ms(16) }}>适配字体</Text>
<View style={{ width: wp(50), height: vs(120), backgroundColor: "skyblue" }} />
</View>
);
}
真实大厂适配方案组合建议
| 场景 | 推荐 |
|---|---|
| 页面布局、按钮宽高 | s / vs 等比缩放 |
| 字体大小 | ms()(更柔和,不会变大太夸张) |
| 全屏组件 (Swiper / Banner) | wp / hp |
| iOS 刘海屏适配 | react-native-safe-area-context |
npm i react-native-safe-area-context
import { SafeAreaView } from "react-native-safe-area-context";
<SafeAreaView style={{ flex:1 }}>
<App/>
</SafeAreaView>
最后给你一句行业经验总结
组件宽高 = s() / vs()
字体 = ms()
全屏比例 = wp() / hp()
外加 SafeAreaView 适配刘海屏
举例根据设计图来实现适配方案
🎯 设计稿 & RN 换算规则
| 设计图 750px | 手机实际宽度≈375dp | 换算比 = 375 / 750 = 0.5 |
|---|
所以换算逻辑
| 设计稿(px) | RN 等效尺寸(dp) |
|---|---|
| 300px | 150dp |
| 100px | 50dp |
| 文字 24px | 12dp |
| 设计稿值 | RN写法 |
|---|---|
宽300px → s(300) |
|
高100px → vs(100) |
|
文字24px → ms(24) |
import { View, Text, Image, StyleSheet } from "react-native";
import { s, vs, ms } from "../utils/scale";
export default function Demo() {
return (
<View style={styles.box}>
<Image
source={{ uri: "xxx.png" }}
style={{ width: s(300), height: vs(100), borderRadius: s(10) }}
/>
<Text style={{ fontSize: ms(24), marginTop: vs(20) }}>
商品标题文字
</Text>
</View>
);
}
const styles = StyleSheet.create({
box: {
padding: s(30),
backgroundColor: "#fff",
}
});
🏆 记住一个黄金公式\
UI稿是多少px,RN就写 s(x) / vs(x) / ms(px)
永远不用算 x/2 或 rem rpx 换算
屏幕再大也自动适配
路径别名
可以!React Native 项目完全可以像 Vue / UniApp一样使用 @/utils/scale 别名路径
不用再写 .../.../.../utils/scale 这种累死人写法。
npm i -D babel-plugin-module-resolver
yarn add -D metro-react-native-babel-preset
修改 babel.config.js
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
[
'module-resolver',
{
root: ['./src'],
extensions: ['.js', '.ts', '.tsx', '.json'],
alias: {
'@': './src',
'@utils': './src/utils',
},
},
],
],
};
如果不行 需要执行 yarn start --reset-cache 重启后再次启动项目
RN中样式 排列对齐方式
基本样式写法
-
RN 的样式主要通过 StyleSheet.create() 来写,也可以直接用对象:
import { StyleSheet, View, Text, Image } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1, // 占满父容器
backgroundColor: '#f5f5f5', // 背景色
alignItems: 'center', // 水平居中
justifyContent: 'center', // 垂直居中
},
title: {
fontSize: 24, // 字体大小
color: '#333', // 文字颜色
fontWeight: 'bold', // 加粗
},
bgImage: {
width: 300,
height: 200,
resizeMode: 'cover', // 图片填充模式
},
});export default function App() {
return (
<View style={styles.container}>
<Text style={styles.title}>Hello React Native</Text>
<Image
style={styles.bgImage}
source={{ uri: 'https://example.com/bg.png' }}
/>
</View>
);
}
样式属性总结
- 布局相关
Flex 布局(RN 默认是 flexDirection: 'column')
container: {
flex: 1,
flexDirection: 'row', // row 水平排列,column 垂直排列
justifyContent: 'center', // 主轴对齐
alignItems: 'center', // 交叉轴对齐
}
| 属性 | 说明 |
|---|---|
| flex | 占用父容器比例 |
| flexDirection | 主轴方向,row / column |
| justifyContent | 主轴对齐,flex-start / center / flex-end / space-between / space-around |
| alignItems | 交叉轴对齐,flex-start / center / flex-end / stretch |
-
背景相关
viewStyle: {
backgroundColor: '#ff0000', // 背景色
}
-
RN 没有 background-image,背景图要用 或
import { ImageBackground } from 'react-native';
<ImageBackground
style={{ width: '100%', height: 200 }}
source={{ uri: 'https://example.com/bg.png' }}</ImageBackground><Text>背景图上的文字</Text>
-
文字相关
textStyle: {
fontSize: 24, // 字号
color: '#333', // 颜色
fontWeight: 'bold', // 加粗
fontStyle: 'italic',// 斜体
textAlign: 'center',// 水平对齐 left/center/right
lineHeight: 28, // 行高
} -
边距与内边距
box: {
margin: 10, // 外边距
marginVertical: 5, // 上下外边距
marginHorizontal: 10, // 左右外边距
padding: 10, // 内边距
paddingHorizontal: 20,
paddingVertical: 15,
} -
圆角、边框、阴影
box: {
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 8, // 圆角
shadowColor: '#000', // 阴影(iOS)
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 4,
elevation: 5, // 阴影(Android)
} -
宽高单位
-
RN 不支持 px / rem,直接写数字就是像素(密度独立像素 dp)
-
可以结合 屏幕适配工具,比如 react-native-size-matters 或自己封装 scale
import { s, vs, ms } from '@utils/scale';
const styles = StyleSheet.create({
button: {
width: s(300), // scale 宽度
height: vs(50), // scale 高度
},
});
常用技巧
-
组合样式
<View style={[styles.box, { backgroundColor: 'red' }]}></View>
-
条件样式
<Text style={[styles.text, isActive && styles.activeText]}></Text>
-
图片背景用 ,文字可以叠加上去