3、项目初始化与目录结构:用CLI搭好架子,后面才不慌
说实话,很多新手拿到一个移动端CRM项目,第一件事就是急着写代码。我见过不少团队,项目跑起来了,但目录乱得像一锅粥,找文件全靠缘分。嗯,咱们今天就把这第一步走稳了。
我个人习惯是,项目初始化花10分钟,后面能省下10小时。你想想看,一个CRM系统少说几十个页面,上百个组件,目录结构要是没规划好,后期维护起来真的会崩溃。
3.1 使用CLI创建项目
咱们用React Native CLI来创建项目。为什么不用Expo?我在项目中遇到过几次Expo的Native模块限制,后来还是切回了CLI。对于CRM这种需要深度定制的企业级应用,CLI更灵活。
npx react-native init CRMApp --template react-native-template-typescript
这条命令会创建一个带TypeScript模板的项目。如果你用的是RN 0.71以上版本,TypeScript已经是默认配置了,直接这样就行:
npx @react-native-community/cli init CRMApp
3.2 理解项目目录结构
项目创建完后,你会看到一堆文件夹。别慌,咱们一个一个看。说白了,核心就这几个:
CRMApp/
├── android/ # Android原生代码
├── ios/ # iOS原生代码
├── src/ # 咱们的主战场(自己创建)
├── __tests__/ # 测试文件
├── index.js # 入口文件
├── App.tsx # 根组件
├── package.json # 项目配置
├── tsconfig.json # TypeScript配置
└── babel.config.js # Babel配置
这里我要重点说一下src/目录。默认项目没有这个文件夹,我建议你手动创建。为什么?因为所有业务代码都应该放在src/里,根目录只放配置文件。这是我踩过坑后养成的习惯。
咱们CRM项目的src/目录,我一般这样组织:
src/
├── components/ # 公共组件
│ ├── common/ # 通用组件(按钮、输入框等)
│ └── business/ # 业务组件(客户卡片、订单列表等)
├── screens/ # 页面
│ ├── Login/ # 登录页
│ ├── Customer/ # 客户管理
│ ├── Order/ # 订单管理
│ └── Dashboard/ # 仪表盘
├── navigation/ # 导航配置
├── services/ # API请求
├── store/ # 状态管理
├── utils/ # 工具函数
├── hooks/ # 自定义Hook
├── types/ # TypeScript类型
└── assets/ # 静态资源
核心原则:按功能模块划分,而不是按文件类型划分。比如把"客户管理"相关的页面、组件、样式都放在一起,而不是把所有页面放一个文件夹,所有组件放另一个。这样找人方便,改起来也快。
3.3 配置package.json
package.json是项目的"身份证"。咱们CRM系统需要安装一些必备依赖。我个人习惯先把这些装上:
{
"name": "CRMApp",
"version": "1.0.0",
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint . --ext .ts,.tsx"
},
"dependencies": {
"react": "18.2.0",
"react-native": "0.72.0",
"@react-navigation/native": "^6.1.0",
"@react-navigation/stack": "^6.3.0",
"axios": "^1.4.0",
"react-native-vector-icons": "^10.0.0",
"react-native-safe-area-context": "^4.7.0"
},
"devDependencies": {
"typescript": "^5.0.0",
"@types/react": "^18.2.0",
"@types/react-native": "^0.72.0",
"jest": "^29.5.0",
"@testing-library/react-native": "^12.0.0"
}
}
这里我解释一下为什么选这些依赖:
- React Navigation: CRM系统页面多,导航复杂,这个库最成熟
- Axios: 处理API请求,拦截器做token刷新很方便
- react-native-vector-icons: 图标库,CRM里各种状态图标用得上
3.4 设置TypeScript
TypeScript对于CRM这种大型项目来说,不是可选项,是必需品。为什么?你想想看,一个客户对象可能有几十个字段,用JS写的话,传参传错了都不知道。TypeScript能在编译时就帮你揪出这些错误。
咱们的tsconfig.json这样配:
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"lib": ["es2017"],
"allowJs": true,
"jsx": "react-native",
"strict": true,
"moduleResolution": "node",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "babel.config.js"]
}
这里有个关键配置——paths。我设置了@/*指向src/*,这样导入文件时就不用写一长串相对路径了。比如:
// 不用这样写
import { CustomerCard } from '../../components/business/CustomerCard';
// 可以这样写
import { CustomerCard } from '@/components/business/CustomerCard';
嗯,这个配置需要在babel.config.js里也同步一下:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module-resolver',
{
root: ['./'],
alias: {
'@': './src',
},
},
],
],
};
最后,咱们定义几个CRM系统的基础类型。这些类型会贯穿整个项目:
// src/types/index.ts
// 客户信息
export interface Customer {
id: string;
name: string;
phone: string;
company: string;
level: 'A' | 'B' | 'C'; // A:高意向 B:中意向 C:低意向
status: 'new' | 'contacted' | 'negotiating' | 'closed';
createdAt: string;
updatedAt: string;
}
// 订单信息
export interface Order {
id: string;
customerId: string;
amount: number;
status: 'pending' | 'confirmed' | 'shipped' | 'completed';
items: OrderItem[];
createdAt: string;
}
// 订单项
export interface OrderItem {
productId: string;
productName: string;
quantity: number;
price: number;
}
// API响应格式
export interface ApiResponse<T> {
code: number;
message: string;
data: T;
}
有了这些类型定义,后面写业务逻辑时,IDE的智能提示会帮你省下大量时间。说白了,TypeScript就是给你的代码加了一层"安全带",开快车也不怕翻。
好了,项目架子搭好了。下一章咱们开始写第一个页面——登录页。到时候你会感谢今天把目录结构理清楚的自己。