React Native —— 1. 使用 Expo 创建一个新项目

1,357 阅读2分钟

Expo Documentation

安装 Expo 脚手架

npm install -g expo-cli

创建一个 Typescript 项目

Use TypeScript - Expo Documentation

  1. 根据官方模板创建新项目

    npx create-expo-app -t expo-template-blank-typescript
    
  2. package.json 添加 script

    {
      "scripts": {
        "ts:check": "tsc"
        ... 
      }
    }
    
  3. 对项目进行类型检查

    yarn tsc
    

项目目录组织

我个人习惯会把项目代码都放在 src目录下面,所以在根目录增加 src 文件夹,并在 src 文件夹下新增以下文件夹

  1. components: 用于存放公共组件
  2. constants: 用于存放公共变量、主题色等
  3. hooks: 自定义 hook
  4. locales: 国际化
  5. navigations: 页面导航
  6. request: axios 封装以及接口 api
  7. screens: 页面
  8. store: 状态管理
  9. types: 类型定义
  10. utils: 封装公共方法

image-20231227094206062.png

src 路径别名

由于我们新建了 src 目录,通常使用 @ 符号来作为 src 目录的路径别名,接下来进行别名配置

  1. 修改tsconfig.json,增加 baseUrlpaths 这里配置了 ~@ 两个别名,~ 指向根目录,@ 指向 src

    {
      "extends": "expo/tsconfig.base",
      "compilerOptions": {
        "strict": true,
        // 增加以下两个配置   
        "baseUrl": "./",
        "paths": {
          "~/*": ["*"],
          "@/*": ["src/*"]
        }
      }
    }
    
  2. 增加 babel-plugin-module-resolver,用户 babel 打包的时候进行路径解析

    yarn add babel-plugin-module-resolver -D
    

    修改 babel.config.js

    module.exports = function (api) {
      api.cache(true);
      return {
        presets: ['babel-preset-expo'],
        // 增加以下代码   
        plugins: [
          [
            'module-resolver',
            {
              root: ['.'],
              extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
              alias: {
                '~': '.',
                '@': ['./src']
              }
            }
          ]
        ]
      };
    };
    
  3. 验证一下

    • src/utils 新建 index.ts,增加以下代码

      export function sum(a: number, b: number) {
        return a + b
      }
      
    • 修改 App.tsx 文件

      import { StatusBar } from 'expo-status-bar';
      import { Image, StyleSheet, Text, View } from 'react-native';
      import { sum } from '@/utils';
      import icon from '~/assets/icon.png';
      
      export default function App() {
        return (
          <View style={styles.container}>
            <Image source={icon} style={{ height: 100, width: 100 }}/>
            <Text>{sum(1, 2)}</Text>
            <Text>Open up App.tsx to start working on your app!</Text>
            <StatusBar style="auto" />
          </View>
        );
      }
      
      const styles = StyleSheet.create({
        container: {
          flex: 1,
          backgroundColor: '#fff',
          alignItems: 'center',
          justifyContent: 'center',
        },
      });
      
      
    • 运行 yarn start --reset-cache,运行成功后发现@~ 两个别名导入都成功生效了

配置 tsconfig.json

我们发现在刚才通过 import 导入图片时,ts 类型检查报错了,提示我们找不到这个类型声明

image.png

接下来我们解决这个问题

  1. scr/types下新建 typings.d.ts 输入以下内容

    declare module '*.png';
    declare module '*.jpg';
    declare module '*.jpeg';
    
  2. 修改 tsconfig.json

    {
      "extends": "expo/tsconfig.base",
      "compilerOptions": {
        "baseUrl": ".",
        "strict": true,
        "sourceMap": true,
        "jsx": "react-native",
        "typeRoots": ["src/types", "./node_modules/@types"],
        "paths": {
          "~/*": ["*"],
          "@/*": ["src/*"]
        },
      },
      "include": [
        "**/*.ts",
        "**/*.tsx"
      ]
    }
    

这时再打开 App.tsx 会发现报错信息已经消失了

配置 .prettierrc

为了保持团队协作中所有成员的代码风格一致,我们使用 Prettier 进行代码风格规范

  1. 安装 vscode 插件,打开 vscode 插件市场搜索 Prettier - Code formatter
  2. 在根目录增加 .prettierrc 文件
  3. 添加以下代码,有自己需求的可以参考 prettier配置 - 简书 (jianshu.com)
    {
      "arrowParens": "always",
      "bracketSpacing": true,
      "endOfLine": "lf",
      "htmlWhitespaceSensitivity": "css",
      "insertPragma": false,
      "singleAttributePerLine": false,
      "bracketSameLine": false,
      "jsxBracketSameLine": false,
      "jsxSingleQuote": false,
      "printWidth": 100,
      "proseWrap": "always",
      "quoteProps": "as-needed",
      "requirePragma": false,
      "semi": true,
      "singleQuote": false,
      "tabWidth": 2,
      "trailingComma": "es5",
      "useTabs": false,
      "embeddedLanguageFormatting": "auto",
      "vueIndentScriptAndStyle": false,
      "parser": "typescript"
    }