作者:Serif COLAKEL
原文:dev.to/samchon/i-m…
本文将指导您使用styled-components和TypeScript设置Expo项目。该项目支持主题系统、暗黑模式以及类型安全的UI组件,为现代React Native应用程序提供了一个强大的基础。
🚀 特性
- Styled Components:利用TypeScript的styled-components。
- Expo Router:简化的导航管理。
- 暗黑/亮色主题:基于系统偏好的内置主题切换。
- 预配置组件:即用型、可定制的UI元素。
- 一致的设计:标准化的间距和排版系统。
- 类型安全:完全类型化的主题和组件。
🛠️ 快速入门
步骤 1:创建新的Expo项目
运行以下命令初始化新的Expo项目:
npx create-expo-app styled-setup --template
# 选择模板:➟ 空白 (TypeScript)
步骤 2:安装依赖项
安装styled-components所需的依赖项:
# 安装styled-components
npm install styled-components
# 安装styled-components的类型定义
npm install @types/styled-components-react-native --save-dev
📂 项目结构
使用以下结构组织您的项目:
├── app/ # Expo Router应用目录
│ ├── (tabs)/ # 标签导航
│ │ ├── index.tsx # 第一个标签屏幕
│ │ ├── two.tsx # 第二个标签屏幕
│ │ └── _layout.tsx # 标签布局配置
│ ├── _layout.tsx # 根布局
│ ├── modal.tsx # 模态屏幕
│ └── +not-found.tsx # 404屏幕
├── components/
│ ├── ui/ # UI组件
│ │ ├── button/
│ │ ├── container/
│ │ ├── text/
│ │ └── layout/
│ └── ExternalLink.tsx
├── themes/ # 主题配置
│ ├── colors.ts # 颜色定义
│ ├── sizes.ts # 尺寸比例
│ ├── spacing.ts # 间距系统
│ ├── styles.ts # 常用样式
│ ├── theme.d.ts # 主题类型定义
│ └── index.ts # 主题导出
└── hooks/ # 自定义钩子
└── useColors.ts # 主题颜色钩子
✨ 核心组件
按钮组件
Button组件是一个灵活的、样式化的按钮,支持变体、尺寸和加载状态。
import Button from "@/components/ui/button";
// 使用
<Button variant="primary" size="lg" shape="rounded" loading={false}>
点击我
</Button>;
Props:
variant
:'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info'
size
:'sm' | 'md' | 'lg' | 'xl'
shape
:'square' | 'rounded' | 'roundedLg' | 'circular'
loading
:boolean
disabled
:boolean
Flex布局
Flex和FlexItem组件提供了一个受CSS flexbox启发的灵活布局系统。
import { Flex, FlexItem } from "@/components/ui/layout";
// 使用
<Flex direction="row" justify="space-between" align="center" gap="md">
<FlexItem grow={1}>
<Text>内容</Text>
</FlexItem>
</Flex>;
Props:
direction
:'row' | 'column'
justify
:'start' | 'center' | 'end' | 'between' | 'around'
align
:'start' | 'center' | 'end'
gap
:'sm' | 'md' | 'lg' | 'xl'
wrap
:'wrap' | 'nowrap'
🎨 主题系统
颜色
在themes/colors.ts
中定义一致的颜色调色板:
const colors = {
primary: "#3b82f6",
secondary: "#22c55e",
success: "#16a34a",
error: "#dc2626",
warning: "#f59e0b",
info: "#0ea5e9",
// 其他颜色...
};
间距
在themes/spacing.ts
中标准化间距:
const spacing = {
padding: {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
},
// Margin和gap定义...
};
排版
在themes/styles.ts
中定义字体大小:
const fontSizes = {
xs: 8,
sm: 12,
base: 14,
md: 16,
lg: 20,
xl: 24,
// 其他尺寸...
};
🌙 暗黑模式支持
该应用程序动态地适应系统暗黑模式偏好:
function RootLayoutNav() {
const colorScheme = useColorScheme();
return (
<ThemeProvider
theme={{
...themes,
isDark: colorScheme === "dark",
}}
>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
</Stack>
</ThemeProvider>
);
}
🛡️ 类型安全
主题类型
通过themes/theme.d.ts
确保主题类型安全:
import "styled-components/native";
import theme from ".";
export type AppTheme = typeof theme;
declare module "styled-components/native" {
export interface DefaultTheme extends AppTheme {}
}
组件Props
为Button组件定义props:
type ButtonProps = {
variant?: keyof typeof buttonVariants;
size?: keyof typeof buttonSizes;
shape?: keyof typeof buttonShapes;
gap?: keyof typeof buttonGap;
} & TouchableOpacityProps;
🔑 最佳实践
-
主题:
- 使用主题值而不是硬编码。
- 通过props访问值:
${({ theme }) => theme.colors.primary}
。
-
组件组织:
- 将样式化组件分离到
style.tsx
文件中。 - 使用
index.tsx
入口点将相关组件分组在文件夹中。
- 将样式化组件分离到
-
TypeScript:
- 明确定义所有props和组件的类型。
- 在适用的情况下扩展现有的React Native类型。
-
性能:
- 在渲染函数外部定义样式化组件。
- 缓存复杂的组件。
- 最小化props更改。
🏁 结论
本文提供了使用Expo和TypeScript的styled-components的全面设置。凭借强大的主题系统、暗黑模式支持和类型安全组件,这个基础确保了可扩展且可维护的代码库。根据您项目的独特需求,自定义和扩展此设置。