使用Styled Components和TypeScript设置Expo

133 阅读3分钟

作者: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'
  • loadingboolean
  • disabledboolean

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;

🔑 最佳实践

  1. 主题

    • 使用主题值而不是硬编码。
    • 通过props访问值:${({ theme }) => theme.colors.primary}
  2. 组件组织

    • 将样式化组件分离到style.tsx文件中。
    • 使用index.tsx入口点将相关组件分组在文件夹中。
  3. TypeScript

    • 明确定义所有props和组件的类型。
    • 在适用的情况下扩展现有的React Native类型。
  4. 性能

    • 在渲染函数外部定义样式化组件。
    • 缓存复杂的组件。
    • 最小化props更改。

🏁 结论

本文提供了使用Expo和TypeScript的styled-components的全面设置。凭借强大的主题系统、暗黑模式支持和类型安全组件,这个基础确保了可扩展且可维护的代码库。根据您项目的独特需求,自定义和扩展此设置。