Ionic项目结构 #

一、项目目录概览 #

1.1 完整目录结构 #

text
myApp/
├── src/                        # 源代码目录
│   ├── app/                    # 应用主目录
│   ├── assets/                 # 静态资源
│   ├── environments/           # 环境配置
│   ├── theme/                  # 主题样式
│   ├── global.scss             # 全局样式
│   ├── index.html              # 入口HTML
│   ├── main.ts                 # 入口脚本
│   ├── polyfills.ts            # Polyfills
│   ├── test.ts                 # 测试配置
│   └── zone-flags.ts           # Zone标志
├── .browserslistrc             # 浏览器兼容配置
├── .editorconfig               # 编辑器配置
├── .gitignore                  # Git忽略配置
├── .npmrc                      # npm配置
├── angular.json                # Angular配置
├── capacitor.config.ts         # Capacitor配置
├── ionic.config.json           # Ionic配置
├── karma.conf.js               # Karma测试配置
├── package.json                # 项目依赖
├── tsconfig.app.json           # 应用TypeScript配置
├── tsconfig.json               # TypeScript主配置
├── tsconfig.spec.json          # 测试TypeScript配置
└── tslint.json                 # TSLint配置

二、源代码目录(src) #

2.1 应用目录(app) #

Angular项目结构:

text
src/app/
├── app.component.ts            # 根组件
├── app.component.html          # 根模板
├── app.component.scss          # 根样式
├── app.module.ts               # 根模块
├── app-routing.module.ts       # 路由配置
├── core/                       # 核心模块
│   ├── core.module.ts
│   ├── services/               # 全局服务
│   │   ├── api.service.ts
│   │   ├── auth.service.ts
│   │   └── storage.service.ts
│   ├── guards/                 # 路由守卫
│   │   └── auth.guard.ts
│   ├── interceptors/           # HTTP拦截器
│   │   └── auth.interceptor.ts
│   └── models/                 # 数据模型
│       └── user.model.ts
├── shared/                     # 共享模块
│   ├── shared.module.ts
│   ├── components/             # 共享组件
│   │   └── header/
│   ├── directives/             # 共享指令
│   │   └── highlight.directive.ts
│   └── pipes/                  # 共享管道
│       └── filter.pipe.ts
├── features/                   # 功能模块
│   ├── home/
│   │   ├── home.module.ts
│   │   ├── home.page.ts
│   │   ├── home.page.html
│   │   └── home.page.scss
│   ├── detail/
│   └── settings/
└── tabs/                       # 标签页模块
    ├── tabs.module.ts
    ├── tabs.page.ts
    └── tabs.router.module.ts

React项目结构:

text
src/
├── app/                        # 应用配置
│   └── store.ts                # 状态管理
├── components/                 # 组件目录
│   ├── common/                 # 通用组件
│   │   ├── Header.tsx
│   │   └── Footer.tsx
│   └── features/               # 功能组件
│       └── UserCard.tsx
├── hooks/                      # 自定义Hooks
│   ├── useAuth.ts
│   └── useApi.ts
├── pages/                      # 页面目录
│   ├── Home.tsx
│   ├── Detail.tsx
│   └── Settings.tsx
├── services/                   # 服务目录
│   ├── api.ts
│   └── auth.ts
├── theme/                      # 主题样式
│   └── variables.css
├── types/                      # 类型定义
│   └── index.d.ts
├── utils/                      # 工具函数
│   └── helpers.ts
├── App.tsx                     # 根组件
├── App.css                     # 根样式
├── main.tsx                    # 入口文件
└── routing.tsx                 # 路由配置

Vue项目结构:

text
src/
├── assets/                     # 静态资源
├── components/                 # 组件目录
│   ├── common/                 # 通用组件
│   └── features/               # 功能组件
├── composables/                # 组合式函数
│   ├── useAuth.ts
│   └── useApi.ts
├── pages/                      # 页面目录
│   ├── Home.vue
│   ├── Detail.vue
│   └── Settings.vue
├── router/                     # 路由配置
│   └── index.ts
├── stores/                     # 状态管理
│   └── user.ts
├── theme/                      # 主题样式
│   └── variables.css
├── types/                      # 类型定义
│   └── index.d.ts
├── utils/                      # 工具函数
│   └── helpers.ts
├── App.vue                     # 根组件
└── main.ts                     # 入口文件

2.2 静态资源目录(assets) #

text
src/assets/
├── icon/                       # 图标
│   ├── favicon.ico
│   └── logo.png
├── images/                     # 图片
│   ├── backgrounds/
│   └── avatars/
├── fonts/                      # 字体
│   └── custom-font.woff2
└── data/                       # 静态数据
    └── config.json

引用资源:

typescript
// TypeScript中引用
import logo from 'src/assets/icon/logo.png';

// 模板中引用
<img [src]="logo" alt="Logo">

// CSS中引用
background-image: url('src/assets/images/bg.png');

2.3 环境配置目录(environments) #

text
src/environments/
├── environment.ts              # 开发环境
└── environment.prod.ts         # 生产环境

environment.ts:

typescript
export const environment = {
  production: false,
  apiUrl: 'http://localhost:3000/api',
  enableDebug: true
};

environment.prod.ts:

typescript
export const environment = {
  production: true,
  apiUrl: 'https://api.example.com',
  enableDebug: false
};

使用环境变量:

typescript
import { environment } from 'src/environments/environment';

@Injectable({ providedIn: 'root' })
export class ApiService {
  private apiUrl = environment.apiUrl;
  
  constructor(private http: HttpClient) {}
  
  getUsers() {
    return this.http.get(`${this.apiUrl}/users`);
  }
}

2.4 主题目录(theme) #

text
src/theme/
├── variables.scss              # CSS变量定义
├── common.scss                 # 通用样式
└── mixins.scss                 # Sass混入

variables.scss:

scss
:root {
  --ion-color-primary: #3880ff;
  --ion-color-secondary: #5260ff;
  --ion-color-tertiary: #6a64ff;
  --ion-color-success: #2dd36f;
  --ion-color-warning: #ffc409;
  --ion-color-danger: #eb445a;
  --ion-color-dark: #222428;
  --ion-color-medium: #92949c;
  --ion-color-light: #f4f5f8;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ion-background-color: #1a1a1a;
    --ion-text-color: #ffffff;
  }
}

三、配置文件详解 #

3.1 package.json #

json
{
  "name": "my-app",
  "version": "0.0.1",
  "author": "Your Name",
  "homepage": "https://yourwebsite.com",
  "scripts": {
    "ng": "ng",
    "start": "ionic serve",
    "build": "ionic build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "cap:init": "cap init",
    "cap:add:ios": "cap add ios",
    "cap:add:android": "cap add android",
    "cap:sync": "cap sync",
    "cap:run:ios": "cap run ios",
    "cap:run:android": "cap run android"
  },
  "dependencies": {
    "@angular/common": "^17.0.0",
    "@angular/core": "^17.0.0",
    "@capacitor/core": "^6.0.0",
    "@ionic/angular": "^8.0.0",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.0"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^17.0.0",
    "@angular/cli": "^17.0.0",
    "@capacitor/cli": "^6.0.0",
    "@ionic/angular-toolkit": "^11.0.0",
    "@types/node": "^20.0.0",
    "typescript": "~5.2.0"
  }
}

3.2 ionic.config.json #

json
{
  "name": "my-app",
  "integrations": {
    "capacitor": {}
  },
  "type": "angular",
  "id": "abc123"
}

3.3 capacitor.config.ts #

typescript
import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.myapp',
  appName: 'My App',
  webDir: 'www',
  bundledWebRuntime: false,
  server: {
    androidScheme: 'https'
  },
  plugins: {
    SplashScreen: {
      launchShowDuration: 2000,
      backgroundColor: '#3880ff',
      showSpinner: false
    },
    Keyboard: {
      resize: 'body',
      resizeOnFullScreen: true
    }
  }
};

export default config;

3.4 angular.json #

json
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "app": {
      "projectType": "application",
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "www",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": [
              {
                "glob": "**/*",
                "input": "src/assets",
                "output": "assets"
              }
            ],
            "styles": [
              "src/theme/variables.scss",
              "src/global.scss"
            ],
            "scripts": []
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "app:build"
          }
        }
      }
    }
  }
}

3.5 tsconfig.json #

json
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "ES2022",
    "module": "ES2022",
    "lib": ["ES2022", "dom"],
    "paths": {
      "@/*": ["src/*"],
      "@app/*": ["src/app/*"],
      "@env/*": ["src/environments/*"]
    }
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  }
}

四、入口文件详解 #

4.1 index.html #

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>My App</title>
  <base href="/">
  
  <meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <meta name="color-scheme" content="light dark">
  <meta name="format-detection" content="telephone=no">
  <meta name="msapplication-tap-highlight" content="no">
  
  <link rel="icon" type="image/png" href="assets/icon/favicon.png">
  <link rel="apple-touch-icon" href="assets/icon/apple-touch-icon.png">
  
  <meta name="theme-color" content="#3880ff">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
</head>

<body>
  <app-root></app-root>
</body>
</html>

4.2 main.ts #

typescript
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .catch(err => console.log(err));

4.3 global.scss #

scss
/* 全局样式 */
@import "~@ionic/angular/css/core.css";
@import "~@ionic/angular/css/normalize.css";
@import "~@ionic/angular/css/structure.css";
@import "~@ionic/angular/css/typography.css";
@import "~@ionic/angular/css/display.css";
@import "~@ionic/angular/css/padding.css";
@import "~@ionic/angular/css/float-elements.css";
@import "~@ionic/angular/css/text-alignment.css";
@import "~@ionic/angular/css/text-transformation.css";
@import "~@ionic/angular/css/flex-utils.css";

/* 自定义全局样式 */
ion-content {
  --background: var(--ion-background-color);
}

ion-toolbar {
  --background: var(--ion-color-primary);
  --color: #ffffff;
}

/* 通用工具类 */
.text-center {
  text-align: center;
}

.mt-10 {
  margin-top: 10px;
}

.mb-10 {
  margin-bottom: 10px;
}

五、模块组织最佳实践 #

5.1 核心模块(Core Module) #

typescript
// core/core.module.ts
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';

import { ApiService } from './services/api.service';
import { AuthService } from './services/auth.service';
import { StorageService } from './services/storage.service';
import { AuthGuard } from './guards/auth.guard';
import { AuthInterceptor } from './interceptors/auth.interceptor';

@NgModule({
  imports: [
    CommonModule,
    HttpClientModule
  ],
  providers: [
    ApiService,
    AuthService,
    StorageService,
    AuthGuard,
    AuthInterceptor
  ]
})
export class CoreModule {
  constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
    if (parentModule) {
      throw new Error('CoreModule已经加载,只能在AppModule中导入');
    }
  }
}

5.2 共享模块(Shared Module) #

typescript
// shared/shared.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';

import { HeaderComponent } from './components/header/header.component';
import { FooterComponent } from './components/footer/footer.component';
import { HighlightDirective } from './directives/highlight.directive';
import { FilterPipe } from './pipes/filter.pipe';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    IonicModule
  ],
  declarations: [
    HeaderComponent,
    FooterComponent,
    HighlightDirective,
    FilterPipe
  ],
  exports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    IonicModule,
    HeaderComponent,
    FooterComponent,
    HighlightDirective,
    FilterPipe
  ]
})
export class SharedModule {}

5.3 功能模块(Feature Module) #

typescript
// features/user/user.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { FormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';

import { UserListPage } from './pages/user-list/user-list.page';
import { UserDetailPage } from './pages/user-detail/user-detail.page';
import { UserService } from './services/user.service';

const routes: Routes = [
  { path: '', component: UserListPage },
  { path: ':id', component: UserDetailPage }
];

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    RouterModule.forChild(routes)
  ],
  declarations: [
    UserListPage,
    UserDetailPage
  ],
  providers: [
    UserService
  ]
})
export class UserModule {}

六、原生平台目录 #

6.1 iOS目录 #

text
ios/
├── App/
│   ├── App/
│   │   ├── Assets.xcassets/    # 资源文件
│   │   ├── AppDelegate.swift   # 应用代理
│   │   ├── Info.plist          # 应用配置
│   │   └── capacitor.config.json
│   ├── App.xcworkspace/        # Xcode工作空间
│   └── Podfile                 # CocoaPods配置
└── Podfile.lock

6.2 Android目录 #

text
android/
├── app/
│   ├── src/
│   │   ├── main/
│   │   │   ├── assets/         # 资源文件
│   │   │   ├── java/           # Java代码
│   │   │   ├── res/            # Android资源
│   │   │   └── AndroidManifest.xml
│   │   └── debug/
│   ├── build.gradle            # 构建配置
│   └── capacitor.build.gradle
├── gradle/
├── build.gradle                # 项目构建配置
├── settings.gradle             # 项目设置
└── gradlew                     # Gradle包装器

七、构建输出目录 #

7.1 Web输出(www) #

text
www/
├── assets/                     # 静态资源
├── index.html                  # 入口文件
├── main.js                     # 主脚本
├── polyfills.js                # Polyfills
├── runtime.js                  # 运行时
├── styles.js                   # 样式
└── *.js.map                    # Source Maps

7.2 构建命令 #

bash
# 开发构建
ionic build

# 生产构建
ionic build --prod

# 指定平台
ionic build --platform=ios
ionic build --platform=android

八、最佳实践 #

8.1 目录命名规范 #

类型 规范 示例
目录 小写+连字符 user-profile
组件 大驼峰+目录 user-card/
服务 小写+点 user.service.ts
页面 小写+点+page home.page.ts
模块 小写+点+module user.module.ts

8.2 模块划分原则 #

text
原则:
1. 核心模块只加载一次
2. 共享模块可被多次导入
3. 功能模块按需懒加载
4. 每个功能模块独立完整

8.3 代码组织建议 #

text
建议:
1. 相关文件放同一目录
2. 按功能而非类型组织
3. 保持目录结构扁平
4. 使用索引文件导出

九、总结 #

9.1 关键要点 #

要点 说明
src目录 所有源代码存放位置
app目录 应用核心代码
assets目录 静态资源文件
environments目录 环境配置
theme目录 主题样式

9.2 下一步 #

了解了项目结构后,接下来让我们学习 UI组件,掌握Ionic丰富的界面组件!

最后更新:2026-03-28