2.1 UniApp项目结构详解

2.1.1 标准项目目录结构

my-uniapp-project/
├── .hbuilderx/              # HBuilderX配置目录
│   └── launch.json         # 运行配置
├── dist/                   # 编译输出目录
│   ├── build/             # 构建配置
│   ├── dev/               # 开发模式输出
│   └── h5/                # H5编译输出
├── node_modules/           # 依赖包目录
├── platforms/              # 原生平台代码
│   ├── android/           # Android平台
│   └── ios/               # iOS平台
├── src/                    # 源代码目录
│   ├── components/        # 自定义组件
│   │   ├── common/        # 通用组件
│   │   └── business/      # 业务组件
│   ├── pages/             # 页面文件
│   │   ├── index/         # 首页
│   │   │   ├── index.vue
│   │   │   └── index.scss
│   │   └── tabBar/        # 标签页
│   ├── static/            # 静态资源
│   │   ├── images/        # 图片资源
│   │   ├── fonts/         # 字体文件
│   │   └── icons/         # 图标文件
│   ├── store/             # 状态管理
│   │   ├── modules/       # 模块化store
│   │   └── index.js       # store入口
│   ├── utils/             # 工具函数
│   │   ├── request.js     # 网络请求
│   │   ├── storage.js     # 本地存储
│   │   └── common.js      # 通用工具
│   ├── mixins/            # 混入文件
│   ├── filters/           # 过滤器
│   ├── directives/        # 自定义指令
│   ├── App.vue            # 应用入口组件
│   ├── main.js            # 应用入口文件
│   ├── manifest.json      # 应用配置
│   ├── pages.json         # 页面路由配置
│   └── uni.scss           # 全局样式变量
├── .gitignore             # Git忽略文件
├── package.json           # 项目配置
├── README.md              # 项目说明
└── vue.config.js          # Vue配置文件

2.1.2 核心文件详解

1. App.vue - 应用入口组件

<template>
  <view id="app">
    <!-- 应用的根视图 -->
  </view>
</template>

<script>
export default {
  name: 'App',
  
  // 应用生命周期
  onLaunch: function() {
    console.log('App Launch')
    // 应用启动时执行
    this.initApp()
  },
  
  onShow: function() {
    console.log('App Show')
    // 应用显示时执行
  },
  
  onHide: function() {
    console.log('App Hide')
    // 应用隐藏时执行
  },
  
  methods: {
    initApp() {
      // 初始化应用
      this.checkUpdate()
      this.initGlobalData()
    },
    
    checkUpdate() {
      // 检查应用更新
      // #ifdef APP-PLUS
      plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
        console.log('当前版本:' + widgetInfo.version)
      })
      // #endif
    },
    
    initGlobalData() {
      // 初始化全局数据
      this.$store.dispatch('init')
    }
  }
}
</script>

<style lang="scss">
/* 全局样式 */
@import "@/uni.scss";

#app {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* 通用样式类 */
.container {
  padding: 20rpx;
}

.flex {
  display: flex;
}

.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

.text-center {
  text-align: center;
}

.text-ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
</style>

2. main.js - 应用入口文件

import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
import './utils/permission' // 权限控制
import './utils/interceptor' // 请求拦截器

// 引入全局组件
import CustomButton from '@/components/common/CustomButton.vue'
import LoadingSpinner from '@/components/common/LoadingSpinner.vue'

// 引入全局混入
import globalMixin from '@/mixins/global.js'

// 引入全局过滤器
import * as filters from '@/filters'

// 创建应用实例
const app = createApp(App)

// 使用store
app.use(store)

// 注册全局组件
app.component('CustomButton', CustomButton)
app.component('LoadingSpinner', LoadingSpinner)

// 注册全局混入
app.mixin(globalMixin)

// 注册全局过滤器
Object.keys(filters).forEach(key => {
  app.config.globalProperties[`$${key}`] = filters[key]
})

// 全局属性
app.config.globalProperties.$api = require('@/utils/api.js')
app.config.globalProperties.$utils = require('@/utils/common.js')

// 全局错误处理
app.config.errorHandler = (err, vm, info) => {
  console.error('全局错误:', err)
  console.error('错误信息:', info)
  
  // 错误上报
  // reportError(err, info)
}

// 启动应用
app.mount('#app')

// 导出应用实例(用于调试)
export default app

3. manifest.json - 应用配置文件

{
  "name": "我的UniApp应用",
  "appid": "__UNI__XXXXXXX",
  "description": "基于UniApp开发的跨平台应用",
  "versionName": "1.0.0",
  "versionCode": "100",
  "transformPx": false,
  
  /* 5+App特有相关 */
  "app-plus": {
    "usingComponents": true,
    "nvueStyleCompiler": "uni-app",
    "compilerVersion": 3,
    "splashscreen": {
      "alwaysShowBeforeRender": true,
      "waiting": true,
      "autoclose": true,
      "delay": 0
    },
    "modules": {
      "Bluetooth": {},
      "Camera": {},
      "Contacts": {},
      "Fingerprint": {},
      "iBeacon": {},
      "LivePusher": {},
      "Maps": {},
      "Messaging": {},
      "OAuth": {},
      "Payment": {},
      "Push": {},
      "Share": {},
      "Speech": {},
      "SQLite": {},
      "VideoPlayer": {}
    },
    "distribute": {
      "android": {
        "permissions": [
          "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\" />",
          "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\" />",
          "<uses-permission android:name=\"android.permission.VIBRATE\" />",
          "<uses-permission android:name=\"android.permission.READ_LOGS\" />",
          "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />",
          "<uses-feature android:name=\"android.hardware.camera.autofocus\" />",
          "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />",
          "<uses-permission android:name=\"android.permission.CAMERA\" />",
          "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\" />",
          "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />",
          "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\" />",
          "<uses-permission android:name=\"android.permission.WAKE_LOCK\" />",
          "<uses-permission android:name=\"android.permission.FLASHLIGHT\" />",
          "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\" />"
        ],
        "abiFilters": ["armeabi-v7a", "arm64-v8a"]
      },
      "ios": {
        "dSYMs": false
      },
      "sdkConfigs": {
        "ad": {},
        "maps": {
          "amap": {
            "appkey_ios": "",
            "appkey_android": ""
          }
        },
        "oauth": {
          "weixin": {
            "appid": "",
            "appsecret": ""
          },
          "qq": {
            "appid": ""
          },
          "sina": {
            "appkey": "",
            "appsecret": "",
            "redirect_uri": ""
          }
        },
        "payment": {
          "alipay": {},
          "weixin": {
            "appid": "",
            "mch_id": "",
            "key": ""
          }
        },
        "push": {
          "unipush": {
            "offline": true,
            "title": "应用名称",
            "channelid": "",
            "appkey": "",
            "appsecret": ""
          }
        },
        "share": {
          "weixin": {
            "appid": "",
            "appsecret": ""
          },
          "qq": {
            "appid": ""
          },
          "sina": {
            "appkey": "",
            "appsecret": "",
            "redirect_uri": ""
          }
        }
      }
    }
  },
  
  /* 快应用特有相关 */
  "quickapp": {},
  
  /* 小程序特有相关 */
  "mp-weixin": {
    "appid": "",
    "setting": {
      "urlCheck": false,
      "es6": true,
      "enhance": true,
      "postcss": true,
      "preloadBackgroundData": false,
      "minified": true,
      "newFeature": false,
      "coverView": true,
      "nodeModules": false,
      "autoAudits": false,
      "showShadowRootInWxmlPanel": true,
      "scopeDataCheck": false,
      "uglifyFileName": false,
      "checkInvalidKey": true,
      "checkSiteMap": true,
      "uploadWithSourceMap": true,
      "compileHotReLoad": false,
      "lazyloadPlaceholderEnable": false,
      "useMultiFrameRuntime": true,
      "useApiHook": true,
      "useApiHostProcess": true,
      "babelSetting": {
        "ignore": [],
        "disablePlugins": [],
        "outputPath": ""
      },
      "enableEngineNative": false,
      "useIsolateContext": true,
      "userConfirmedBundleSwitch": false,
      "packNpmManually": false,
      "packNpmRelationList": [],
      "minifyWXSS": true,
      "disableUseStrict": false,
      "minifyWXML": true,
      "showES6CompileOption": false,
      "useCompilerPlugins": false
    },
    "usingComponents": true,
    "permission": {
      "scope.userLocation": {
        "desc": "您的位置信息将用于小程序位置接口的效果展示"
      }
    },
    "requiredPrivateInfos": ["getLocation"]
  },
  
  "mp-alipay": {
    "usingComponents": true
  },
  
  "mp-baidu": {
    "usingComponents": true
  },
  
  "mp-toutiao": {
    "usingComponents": true
  },
  
  "uniStatistics": {
    "enable": false
  },
  
  "vueVersion": "3"
}

4. pages.json - 页面路由配置

{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页",
        "enablePullDownRefresh": true,
        "onReachBottomDistance": 50,
        "backgroundTextStyle": "dark"
      }
    },
    {
      "path": "pages/category/category",
      "style": {
        "navigationBarTitleText": "分类",
        "navigationBarBackgroundColor": "#ffffff",
        "navigationBarTextStyle": "black"
      }
    },
    {
      "path": "pages/cart/cart",
      "style": {
        "navigationBarTitleText": "购物车",
        "navigationBarBackgroundColor": "#ffffff",
        "navigationBarTextStyle": "black"
      }
    },
    {
      "path": "pages/profile/profile",
      "style": {
        "navigationBarTitleText": "我的",
        "navigationBarBackgroundColor": "#ffffff",
        "navigationBarTextStyle": "black"
      }
    },
    {
      "path": "pages/login/login",
      "style": {
        "navigationBarTitleText": "登录",
        "navigationStyle": "custom"
      }
    }
  ],
  
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "UniApp应用",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8",
    "backgroundTextStyle": "light",
    "enablePullDownRefresh": false,
    "onReachBottomDistance": 50,
    "maxWidth": 375,
    "rpxCalcMaxDeviceWidth": 960,
    "rpxCalcBaseDeviceWidth": 375,
    "rpxCalcIncludeWidth": 750
  },
  
  "tabBar": {
    "color": "#7A7E83",
    "selectedColor": "#3cc51f",
    "borderStyle": "black",
    "backgroundColor": "#ffffff",
    "height": "50px",
    "fontSize": "10px",
    "iconWidth": "24px",
    "spacing": "3px",
    "list": [
      {
        "pagePath": "pages/index/index",
        "iconPath": "static/tab-home.png",
        "selectedIconPath": "static/tab-home-current.png",
        "text": "首页"
      },
      {
        "pagePath": "pages/category/category",
        "iconPath": "static/tab-category.png",
        "selectedIconPath": "static/tab-category-current.png",
        "text": "分类"
      },
      {
        "pagePath": "pages/cart/cart",
        "iconPath": "static/tab-cart.png",
        "selectedIconPath": "static/tab-cart-current.png",
        "text": "购物车"
      },
      {
        "pagePath": "pages/profile/profile",
        "iconPath": "static/tab-profile.png",
        "selectedIconPath": "static/tab-profile-current.png",
        "text": "我的"
      }
    ]
  },
  
  "condition": {
    "current": 0,
    "list": [
      {
        "name": "首页",
        "path": "pages/index/index",
        "query": ""
      },
      {
        "name": "登录页",
        "path": "pages/login/login",
        "query": ""
      }
    ]
  },
  
  "subPackages": [
    {
      "root": "pagesA",
      "pages": [
        {
          "path": "detail/detail",
          "style": {
            "navigationBarTitleText": "详情页"
          }
        }
      ]
    },
    {
      "root": "pagesB",
      "pages": [
        {
          "path": "order/order",
          "style": {
            "navigationBarTitleText": "订单页"
          }
        }
      ]
    }
  ],
  
  "preloadRule": {
    "pages/index/index": {
      "network": "all",
      "packages": ["pagesA"]
    }
  }
}

2.1.3 静态资源管理

1. 图片资源组织

src/
├── components/          # 组件目录
│   ├── common/         # 通用组件
│   └── business/       # 业务组件
├── pages/              # 页面目录
├── static/             # 静态资源
├── store/              # 状态管理
├── utils/              # 工具函数
├── api/                # API接口
├── mixins/             # 混入
├── filters/            # 过滤器
├── App.vue             # 应用入口
├── main.js             # 入口文件
├── manifest.json       # 应用配置
└── pages.json          # 页面配置

快速开始

安装依赖

npm install

开发模式

# H5开发
npm run dev:h5

# 微信小程序开发
npm run dev:mp-weixin

# App开发
npm run dev:app-plus

构建发布

# 构建H5
npm run build:h5

# 构建微信小程序
npm run build:mp-weixin

# 构建App
npm run build:app-plus

开发规范

代码规范

  • 使用ESLint进行代码检查
  • 使用Prettier进行代码格式化
  • 遵循Vue官方风格指南
  • 使用语义化的命名

提交规范

feat: 新功能
fix: 修复bug
docs: 文档更新
style: 代码格式调整
refactor: 代码重构
test: 测试相关
chore: 构建过程或辅助工具的变动

常见问题

开发环境问题

  1. Node.js版本兼容性

    • 推荐使用Node.js 14.x或16.x
    • 避免使用过新或过旧的版本
  2. 依赖安装失败

    • 清除缓存:npm cache clean --force
    • 删除node_modules重新安装
    • 使用cnpm或yarn替代npm
  3. 编译错误

    • 检查语法错误
    • 确认依赖版本兼容性
    • 查看控制台错误信息

运行问题

  1. 页面白屏

    • 检查路由配置
    • 确认页面文件存在
    • 查看控制台错误
  2. 样式不生效

    • 检查CSS语法
    • 确认样式文件引入
    • 验证选择器优先级
  3. API请求失败

    • 检查网络连接
    • 确认接口地址正确
    • 验证请求参数

性能优化建议

代码优化

  1. 组件懒加载
  2. 图片压缩和懒加载
  3. 减少不必要的计算
  4. 合理使用缓存

包体积优化

  1. 按需引入第三方库
  2. 移除未使用的代码
  3. 使用分包加载
  4. 压缩静态资源

更新日志

v1.0.0 (2024-01-01)

  • 初始版本发布
  • 基础功能实现
  • 多端适配完成

贡献指南

  1. Fork项目
  2. 创建功能分支
  3. 提交代码
  4. 发起Pull Request

许可证

MIT License


---

## 2.5 本章总结

### 2.5.1 学习要点回顾

**1. 项目结构理解**

- 掌握UniApp标准项目目录结构
- 理解核心配置文件的作用
- 学会合理组织代码和资源
- 掌握静态资源管理方法

**2. 开发工具使用**

- 熟练使用HBuilderX开发环境
- 掌握代码提示和补全功能
- 学会调试和预览技巧
- 了解插件和扩展管理

**3. 项目配置优化**

- 掌握编译配置和条件编译
- 学会性能优化配置
- 理解环境变量和配置管理
- 掌握开发环境配置

**4. 代码规范实践**

- 遵循文件命名规范
- 掌握代码风格规范
- 学会编写规范的注释和文档
- 建立良好的开发习惯

### 2.5.2 实践练习

**练习1:项目结构搭建**

```javascript
// 任务:创建一个电商应用的项目结构
// 要求:
// 1. 合理划分目录结构
// 2. 配置必要的配置文件
// 3. 创建基础页面和组件
// 4. 设置开发环境

// 参考结构:
src/
├── components/
│   ├── common/
│   │   ├── BaseButton.vue
│   │   ├── BaseInput.vue
│   │   └── LoadingSpinner.vue
│   └── business/
│       ├── ProductCard.vue
│       ├── CartItem.vue
│       └── OrderStatus.vue
├── pages/
│   ├── index/
│   ├── category/
│   ├── cart/
│   ├── profile/
│   └── product-detail/
├── store/
│   ├── modules/
│   │   ├── user.js
│   │   ├── product.js
│   │   └── cart.js
│   └── index.js
├── utils/
│   ├── request.js
│   ├── storage.js
│   └── common.js
└── api/
    ├── userApi.js
    ├── productApi.js
    └── orderApi.js

练习2:开发工具配置

// 任务:配置HBuilderX开发环境
// 要求:
// 1. 安装必要的插件
// 2. 配置代码格式化
// 3. 设置代码片段
// 4. 配置调试环境

// 推荐插件列表:
- Prettier代码格式化
- ESLint代码检查
- Auto Rename Tag
- Bracket Pair Colorizer
- GitLens
- Thunder Client

练习3:配置文件编写

// 任务:编写项目配置文件
// 要求:
// 1. 配置manifest.json
// 2. 配置pages.json
// 3. 配置vue.config.js
// 4. 设置环境变量

// 配置要点:
// - 应用基本信息
// - 页面路由配置
// - 编译优化配置
// - 多环境配置

2.5.3 常见问题解答

Q1:如何选择合适的项目结构?

A1:项目结构选择应考虑以下因素: - 项目规模和复杂度 - 团队开发习惯 - 维护和扩展需求 - 性能优化要求

小型项目可使用简单的功能分层结构,大型项目建议使用模块化结构。

Q2:HBuilderX和其他IDE相比有什么优势?

A2:HBuilderX的主要优势: - 专为UniApp优化,提供完整的开发体验 - 内置多端预览和调试功能 - 丰富的代码提示和补全 - 集成的插件生态 - 简化的项目配置和部署流程

Q3:如何处理不同平台的差异化配置?

A3:处理平台差异的方法: - 使用条件编译处理代码差异 - 在manifest.json中配置平台特定选项 - 使用平台检测API动态处理 - 创建平台特定的组件和样式

Q4:项目性能优化有哪些关键点?

A4:性能优化关键点: - 合理的分包策略 - 图片和资源优化 - 代码分割和懒加载 - 缓存策略配置 - 网络请求优化

2.5.4 下章预告

在下一章《基础语法与组件使用》中,我们将学习:

  1. Vue 3基础语法

    • 响应式数据
    • 计算属性和监听器
    • 生命周期钩子
    • 组件通信
  2. UniApp内置组件

    • 视图容器组件
    • 基础内容组件
    • 表单组件
    • 导航组件
  3. 自定义组件开发

    • 组件设计原则
    • 组件封装技巧
    • 组件通信方式
    • 组件库构建
  4. 样式和布局

    • CSS预处理器使用
    • 响应式布局
    • 主题定制
    • 动画效果

通过下一章的学习,你将掌握UniApp开发的核心技能,能够创建功能丰富的用户界面。tatic/ ├── images/ │ ├── common/ # 通用图片 │ │ ├── logo.png │ │ ├── placeholder.png │ │ └── default-avatar.png │ ├── icons/ # 图标文件 │ │ ├── home.png │ │ ├── search.png │ │ └── arrow-right.png │ ├── banners/ # 轮播图 │ │ ├── banner1.jpg │ │ └── banner2.jpg │ └── backgrounds/ # 背景图 │ ├── login-bg.jpg │ └── profile-bg.jpg ├── fonts/ # 字体文件 │ ├── iconfont.ttf │ └── custom-font.woff └── videos/ # 视频文件 └── intro.mp4


**2. 资源引用方式**

```vue
<template>
  <view>
    <!-- 相对路径引用 -->
    <image src="../../static/images/logo.png" />
    
    <!-- 绝对路径引用 -->
    <image src="/static/images/logo.png" />
    
    <!-- @符号引用 -->
    <image src="@/static/images/logo.png" />
    
    <!-- 网络图片 -->
    <image src="https://example.com/image.jpg" />
    
    <!-- 动态绑定 -->
    <image :src="imageUrl" />
  </view>
</template>

<script>
export default {
  data() {
    return {
      imageUrl: '/static/images/dynamic.png'
    }
  }
}
</script>

<style>
/* CSS中引用图片 */
.background {
  background-image: url('@/static/images/bg.jpg');
}

/* 字体文件引用 */
@font-face {
  font-family: 'CustomFont';
  src: url('@/static/fonts/custom-font.ttf');
}
</style>

2.2 HBuilderX开发工具深入

2.2.1 界面布局详解

1. 主界面组成

┌─────────────────────────────────────────────────────────┐
│  菜单栏 (File, Edit, View, Run, Tools, Help)           │
├─────────────────────────────────────────────────────────┤
│  工具栏 (新建, 保存, 运行, 调试等快捷按钮)                │
├──────────┬──────────────────────────┬─────────────────────┤
│          │                          │                     │
│  项目    │                          │    属性面板         │
│  管理器  │      代码编辑区域          │    (可选)           │
│          │                          │                     │
│          │                          │                     │
├──────────┼──────────────────────────┼─────────────────────┤
│  文件    │                          │    控制台           │
│  浏览器  │                          │    输出窗口         │
└──────────┴──────────────────────────┴─────────────────────┘

2. 项目管理器功能

// 项目管理器主要功能
1. 项目树形结构显示
2. 文件/文件夹操作
   - 新建、删除、重命名
   - 复制、粘贴、移动
   - 搜索文件
3. 项目切换
4. Git状态显示
5. 文件类型图标

3. 代码编辑器特性

// 编辑器核心功能
1. 语法高亮
   - Vue单文件组件
   - JavaScript/TypeScript
   - CSS/SCSS/LESS
   - JSON配置文件

2. 智能提示
   - 代码自动补全
   - 参数提示
   - 错误检查
   - 快速修复建议

3. 代码导航
   - 跳转到定义
   - 查找引用
   - 符号搜索
   - 面包屑导航

4. 编辑增强
   - 多光标编辑
   - 代码折叠
   - 括号匹配
   - 自动缩进

2.2.2 代码提示和补全

1. Vue组件提示

<template>
  <!-- 输入 <uni- 会提示所有uni组件 -->
  <uni-list>
    <uni-list-item>
      <!-- 属性提示 -->
      <text :class="textClass">内容</text>
    </uni-list-item>
  </uni-list>
</template>

<script>
export default {
  data() {
    return {
      // 变量提示
      textClass: 'text-primary'
    }
  },
  
  methods: {
    // 方法提示
    handleClick() {
      // API提示
      uni.showToast({
        title: '提示',
        icon: 'success'
      })
    }
  }
}
</script>

2. API智能提示

// UniApp API提示
uni.request({
  url: '', // 自动提示必填参数
  method: '', // 提示可选值:GET, POST, PUT, DELETE
  data: {},
  success: (res) => {
    // res参数自动提示
    console.log(res.data)
  }
})

// 平台API提示
// #ifdef APP-PLUS
plus.device.getInfo({
  success: (info) => {
    // info参数提示
    console.log(info.model)
  }
})
// #endif

3. 自定义代码片段

// 在工具 → 代码块设置中添加
{
  "vue-page": {
    "prefix": "vpage",
    "body": [
      "<template>",
      "  <view class=\"container\">",
      "    $1",
      "  </view>",
      "</template>",
      "",
      "<script>",
      "export default {",
      "  name: '$2',",
      "  data() {",
      "    return {",
      "      $3",
      "    }",
      "  },",
      "  onLoad() {",
      "    $4",
      "  }",
      "}",
      "</script>",
      "",
      "<style lang=\"scss\" scoped>",
      ".container {",
      "  padding: 20rpx;",
      "}",
      "</style>"
    ],
    "description": "Vue页面模板"
  }
}

2.2.3 调试和预览功能

1. 实时预览配置

// .hbuilderx/launch.json 配置
{
  "version": "0.0",
  "configurations": [
    {
      "type": "uniApp",
      "default": {
        "launchtype": "local"
      },
      "h5": {
        "launchtype": "local",
        "port": 8080,
        "host": "localhost"
      },
      "mp-weixin": {
        "launchtype": "local",
        "port": 9090
      },
      "app-plus": {
        "launchtype": "local",
        "android": {
          "device": "emulator-5554"
        },
        "ios": {
          "device": "iPhone 12"
        }
      }
    }
  ]
}

2. 多端同步预览

// 同步预览设置
1. 运行 → 运行到浏览器 → 自动刷新
2. 运行 → 运行到小程序模拟器 → 热重载
3. 运行 → 运行到手机或模拟器 → 真机同步

// 预览模式
- 开发模式:实时编译,支持热重载
- 生产模式:优化编译,用于发布
- 调试模式:包含调试信息,便于排错

3. 断点调试

// 在代码中设置断点
export default {
  methods: {
    handleSubmit() {
      debugger; // 设置断点
      
      const formData = this.getFormData()
      console.log('表单数据:', formData) // 查看变量值
      
      this.submitForm(formData)
    },
    
    getFormData() {
      // 在此行设置断点
      return {
        name: this.name,
        email: this.email
      }
    }
  }
}

2.2.4 插件和扩展管理

1. 内置插件

// 核心插件
1. uni-app语法提示
2. Vue语法支持
3. ES6+语法支持
4. SCSS/LESS编译
5. TypeScript支持
6. 代码格式化
7. Git集成
8. 终端集成

// 调试插件
1. Chrome DevTools
2. 微信开发者工具集成
3. 真机调试
4. 网络抓包

2. 第三方插件安装

// 通过插件市场安装
1. 工具 → 插件安装
2. 搜索插件名称
3. 点击安装
4. 重启HBuilderX

// 推荐插件
- Prettier代码格式化
- ESLint代码检查
- Vetur Vue工具
- Auto Rename Tag
- Bracket Pair Colorizer
- GitLens Git增强
- Thunder Client API测试

3. 插件配置

// settings.json 插件配置
{
  "prettier.enable": true,
  "prettier.semi": false,
  "prettier.singleQuote": true,
  "prettier.tabWidth": 2,
  
  "eslint.enable": true,
  "eslint.autoFixOnSave": true,
  
  "vetur.format.defaultFormatter.html": "prettier",
  "vetur.format.defaultFormatter.js": "prettier",
  "vetur.format.defaultFormatter.css": "prettier"
}

2.3 项目配置优化

2.3.1 编译配置

1. vue.config.js配置

const path = require('path')

module.exports = {
  // 基础配置
  publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
  outputDir: 'dist',
  assetsDir: 'static',
  
  // 开发服务器配置
  devServer: {
    port: 8080,
    host: '0.0.0.0',
    https: false,
    open: true,
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  },
  
  // 路径别名
  configureWebpack: {
    resolve: {
      alias: {
        '@': path.resolve(__dirname, 'src'),
        '@components': path.resolve(__dirname, 'src/components'),
        '@pages': path.resolve(__dirname, 'src/pages'),
        '@utils': path.resolve(__dirname, 'src/utils'),
        '@static': path.resolve(__dirname, 'src/static')
      }
    }
  },
  
  // CSS配置
  css: {
    loaderOptions: {
      sass: {
        prependData: `@import "@/uni.scss";`
      }
    }
  },
  
  // 生产环境优化
  chainWebpack: config => {
    // 生产环境移除console
    if (process.env.NODE_ENV === 'production') {
      config.optimization.minimizer('terser').tap((args) => {
        args[0].terserOptions.compress.drop_console = true
        return args
      })
    }
    
    // 图片压缩
    config.module
      .rule('images')
      .test(/\.(png|jpe?g|gif|svg)$/)
      .use('image-webpack-loader')
      .loader('image-webpack-loader')
      .options({
        mozjpeg: { progressive: true, quality: 80 },
        optipng: { enabled: false },
        pngquant: { quality: [0.65, 0.8], speed: 4 },
        gifsicle: { interlaced: false }
      })
  }
}

2. 条件编译配置

// 平台条件编译
// #ifdef H5
console.log('这段代码只在H5平台运行')
// #endif

// #ifdef MP-WEIXIN
console.log('这段代码只在微信小程序运行')
// #endif

// #ifdef APP-PLUS
console.log('这段代码只在App平台运行')
// #endif

// #ifndef H5
console.log('这段代码在除H5外的平台运行')
// #endif

// 多平台条件编译
// #ifdef H5 || MP-WEIXIN
console.log('这段代码在H5或微信小程序运行')
// #endif
<!-- 模板中的条件编译 -->
<template>
  <view>
    <!-- #ifdef H5 -->
    <view class="h5-only">H5专用内容</view>
    <!-- #endif -->
    
    <!-- #ifdef MP-WEIXIN -->
    <button open-type="getUserInfo" @getuserinfo="getUserInfo">
      获取用户信息
    </button>
    <!-- #endif -->
    
    <!-- #ifdef APP-PLUS -->
    <button @click="openNativeView">打开原生页面</button>
    <!-- #endif -->
  </view>
</template>

<style>
/* 样式中的条件编译 */
/* #ifdef H5 */
.container {
  max-width: 750px;
  margin: 0 auto;
}
/* #endif */

/* #ifdef MP-WEIXIN */
.container {
  padding-top: 88rpx; /* 微信小程序状态栏高度 */
}
/* #endif */
</style>

2.3.2 性能优化配置

1. 分包配置

// pages.json 中配置分包
{
  "pages": [
    // 主包页面
    {
      "path": "pages/index/index",
      "style": { "navigationBarTitleText": "首页" }
    }
  ],
  
  "subPackages": [
    {
      "root": "pagesA",
      "name": "pack1",
      "pages": [
        {
          "path": "detail/detail",
          "style": { "navigationBarTitleText": "详情" }
        },
        {
          "path": "list/list",
          "style": { "navigationBarTitleText": "列表" }
        }
      ]
    },
    {
      "root": "pagesB",
      "name": "pack2",
      "pages": [
        {
          "path": "profile/profile",
          "style": { "navigationBarTitleText": "个人中心" }
        }
      ]
    }
  ],
  
  "preloadRule": {
    "pages/index/index": {
      "network": "all",
      "packages": ["pack1"]
    },
    "pagesA/list/list": {
      "network": "wifi",
      "packages": ["pack2"]
    }
  }
}

2. 资源优化配置

// 图片懒加载配置
const imageConfig = {
  // 图片压缩质量
  quality: 80,
  
  // 图片格式转换
  format: 'webp',
  
  // 响应式图片
  responsive: {
    small: { width: 300, quality: 70 },
    medium: { width: 600, quality: 80 },
    large: { width: 1200, quality: 85 }
  },
  
  // 懒加载配置
  lazyload: {
    placeholder: '/static/images/placeholder.png',
    error: '/static/images/error.png',
    loading: '/static/images/loading.gif'
  }
}

// 网络请求优化
const requestConfig = {
  // 请求超时时间
  timeout: 10000,
  
  // 重试次数
  retry: 3,
  
  // 缓存配置
  cache: {
    enable: true,
    maxAge: 5 * 60 * 1000, // 5分钟
    maxSize: 50 // 最大缓存50个请求
  },
  
  // 请求拦截器
  interceptors: {
    request: (config) => {
      // 添加token
      config.header.Authorization = getToken()
      return config
    },
    response: (response) => {
      // 统一错误处理
      if (response.statusCode !== 200) {
        handleError(response)
      }
      return response
    }
  }
}

2.3.3 开发环境配置

1. 环境变量配置

// .env.development
VUE_APP_ENV = 'development'
VUE_APP_BASE_URL = 'http://localhost:3000'
VUE_APP_API_URL = 'http://localhost:3000/api'
VUE_APP_UPLOAD_URL = 'http://localhost:3000/upload'
VUE_APP_DEBUG = true

// .env.production
VUE_APP_ENV = 'production'
VUE_APP_BASE_URL = 'https://api.example.com'
VUE_APP_API_URL = 'https://api.example.com/api'
VUE_APP_UPLOAD_URL = 'https://api.example.com/upload'
VUE_APP_DEBUG = false

// .env.test
VUE_APP_ENV = 'test'
VUE_APP_BASE_URL = 'https://test-api.example.com'
VUE_APP_API_URL = 'https://test-api.example.com/api'
VUE_APP_UPLOAD_URL = 'https://test-api.example.com/upload'
VUE_APP_DEBUG = true

2. 配置文件管理

// src/config/index.js
const config = {
  development: {
    baseURL: process.env.VUE_APP_BASE_URL,
    apiURL: process.env.VUE_APP_API_URL,
    uploadURL: process.env.VUE_APP_UPLOAD_URL,
    debug: process.env.VUE_APP_DEBUG === 'true',
    
    // 开发环境特有配置
    mockData: true,
    showVConsole: true,
    logLevel: 'debug'
  },
  
  production: {
    baseURL: process.env.VUE_APP_BASE_URL,
    apiURL: process.env.VUE_APP_API_URL,
    uploadURL: process.env.VUE_APP_UPLOAD_URL,
    debug: false,
    
    // 生产环境特有配置
    mockData: false,
    showVConsole: false,
    logLevel: 'error',
    
    // 性能监控
    performance: {
      enable: true,
      reportURL: 'https://monitor.example.com/report'
    }
  },
  
  test: {
    baseURL: process.env.VUE_APP_BASE_URL,
    apiURL: process.env.VUE_APP_API_URL,
    uploadURL: process.env.VUE_APP_UPLOAD_URL,
    debug: true,
    
    // 测试环境特有配置
    mockData: false,
    showVConsole: true,
    logLevel: 'info'
  }
}

const currentEnv = process.env.VUE_APP_ENV || 'development'
export default config[currentEnv]

2.4 代码组织最佳实践

2.4.1 文件命名规范

1. 文件命名约定

命名规范:
- 页面文件:kebab-case (user-profile.vue)
- 组件文件:PascalCase (UserProfile.vue)
- 工具文件:camelCase (userUtils.js)
- 常量文件:UPPER_CASE (API_CONSTANTS.js)
- 样式文件:kebab-case (user-profile.scss)

示例结构:
src/
├── components/
│   ├── common/
│   │   ├── BaseButton.vue
│   │   ├── BaseInput.vue
│   │   └── LoadingSpinner.vue
│   └── business/
│       ├── UserCard.vue
│       ├── ProductList.vue
│       └── OrderStatus.vue
├── pages/
│   ├── user-profile/
│   │   ├── user-profile.vue
│   │   └── user-profile.scss
│   └── product-detail/
│       ├── product-detail.vue
│       └── components/
│           ├── ProductInfo.vue
│           └── ProductReviews.vue
├── utils/
│   ├── requestUtils.js
│   ├── storageUtils.js
│   └── dateUtils.js
└── constants/
    ├── API_CONSTANTS.js
    ├── ROUTE_CONSTANTS.js
    └── STATUS_CONSTANTS.js

2. 目录结构规范

// 按功能模块组织
src/
├── modules/
│   ├── user/
│   │   ├── pages/
│   │   │   ├── profile.vue
│   │   │   └── settings.vue
│   │   ├── components/
│   │   │   ├── UserCard.vue
│   │   │   └── UserForm.vue
│   │   ├── store/
│   │   │   └── userStore.js
│   │   ├── api/
│   │   │   └── userApi.js
│   │   └── utils/
│   │       └── userUtils.js
│   ├── product/
│   │   ├── pages/
│   │   ├── components/
│   │   ├── store/
│   │   ├── api/
│   │   └── utils/
│   └── order/
│       ├── pages/
│       ├── components/
│       ├── store/
│       ├── api/
│       └── utils/
└── shared/
    ├── components/
    ├── utils/
    ├── constants/
    └── styles/

2.4.2 代码风格规范

1. Vue组件规范

<!-- 标准Vue组件模板 -->
<template>
  <view class="user-profile">
    <!-- 使用语义化的class名称 -->
    <view class="user-profile__header">
      <image 
        class="user-profile__avatar" 
        :src="userInfo.avatar" 
        @error="handleAvatarError"
      />
      <text class="user-profile__name">{{ userInfo.name }}</text>
    </view>
    
    <view class="user-profile__content">
      <!-- 组件内容 -->
    </view>
  </view>
</template>

<script>
import { mapState, mapActions } from 'vuex'
import UserApi from '@/api/userApi'
import { validateEmail } from '@/utils/validation'

export default {
  name: 'UserProfile',
  
  // 组件属性
  props: {
    userId: {
      type: String,
      required: true,
      validator: (value) => value.length > 0
    },
    editable: {
      type: Boolean,
      default: false
    }
  },
  
  // 组件数据
  data() {
    return {
      loading: false,
      userInfo: {
        name: '',
        email: '',
        avatar: ''
      }
    }
  },
  
  // 计算属性
  computed: {
    ...mapState('user', ['currentUser']),
    
    isCurrentUser() {
      return this.userId === this.currentUser.id
    },
    
    displayName() {
      return this.userInfo.name || '未知用户'
    }
  },
  
  // 监听器
  watch: {
    userId: {
      handler: 'fetchUserInfo',
      immediate: true
    }
  },
  
  // 生命周期
  onLoad(options) {
    this.initComponent(options)
  },
  
  onShow() {
    this.refreshUserInfo()
  },
  
  // 方法
  methods: {
    ...mapActions('user', ['updateUser']),
    
    async initComponent(options) {
      try {
        this.loading = true
        await this.fetchUserInfo()
      } catch (error) {
        this.handleError(error)
      } finally {
        this.loading = false
      }
    },
    
    async fetchUserInfo() {
      const response = await UserApi.getUserInfo(this.userId)
      this.userInfo = response.data
    },
    
    handleAvatarError() {
      this.userInfo.avatar = '/static/images/default-avatar.png'
    },
    
    handleError(error) {
      console.error('用户信息加载失败:', error)
      uni.showToast({
        title: '加载失败',
        icon: 'none'
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.user-profile {
  padding: 20rpx;
  
  &__header {
    display: flex;
    align-items: center;
    margin-bottom: 30rpx;
  }
  
  &__avatar {
    width: 120rpx;
    height: 120rpx;
    border-radius: 50%;
    margin-right: 20rpx;
  }
  
  &__name {
    font-size: 32rpx;
    font-weight: bold;
    color: #333;
  }
  
  &__content {
    // 内容样式
  }
}
</style>

2. JavaScript代码规范

// utils/requestUtils.js

/**
 * 网络请求工具类
 * @description 封装uni.request,提供统一的请求接口
 */
class RequestUtils {
  constructor() {
    this.baseURL = process.env.VUE_APP_API_URL
    this.timeout = 10000
    this.defaultHeaders = {
      'Content-Type': 'application/json'
    }
  }
  
  /**
   * 发送GET请求
   * @param {string} url - 请求地址
   * @param {Object} params - 请求参数
   * @param {Object} options - 请求选项
   * @returns {Promise} 请求结果
   */
  async get(url, params = {}, options = {}) {
    return this.request({
      url,
      method: 'GET',
      data: params,
      ...options
    })
  }
  
  /**
   * 发送POST请求
   * @param {string} url - 请求地址
   * @param {Object} data - 请求数据
   * @param {Object} options - 请求选项
   * @returns {Promise} 请求结果
   */
  async post(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'POST',
      data,
      ...options
    })
  }
  
  /**
   * 通用请求方法
   * @param {Object} config - 请求配置
   * @returns {Promise} 请求结果
   */
  async request(config) {
    // 请求拦截
    const requestConfig = this.interceptRequest(config)
    
    try {
      const response = await uni.request(requestConfig)
      
      // 响应拦截
      return this.interceptResponse(response)
    } catch (error) {
      return this.handleError(error)
    }
  }
  
  /**
   * 请求拦截器
   * @param {Object} config - 请求配置
   * @returns {Object} 处理后的配置
   */
  interceptRequest(config) {
    // 添加基础URL
    if (!config.url.startsWith('http')) {
      config.url = this.baseURL + config.url
    }
    
    // 添加默认headers
    config.header = {
      ...this.defaultHeaders,
      ...config.header
    }
    
    // 添加认证token
    const token = uni.getStorageSync('token')
    if (token) {
      config.header.Authorization = `Bearer ${token}`
    }
    
    // 设置超时时间
    config.timeout = config.timeout || this.timeout
    
    return config
  }
  
  /**
   * 响应拦截器
   * @param {Object} response - 响应对象
   * @returns {Object} 处理后的响应
   */
  interceptResponse(response) {
    const { statusCode, data } = response
    
    // 请求成功
    if (statusCode === 200) {
      // 业务逻辑成功
      if (data.code === 0) {
        return data
      }
      
      // 业务逻辑失败
      throw new Error(data.message || '请求失败')
    }
    
    // HTTP状态码错误
    throw new Error(this.getErrorMessage(statusCode))
  }
  
  /**
   * 错误处理
   * @param {Error} error - 错误对象
   * @returns {Promise} 拒绝的Promise
   */
  handleError(error) {
    console.error('请求错误:', error)
    
    // 显示错误提示
    uni.showToast({
      title: error.message || '网络错误',
      icon: 'none',
      duration: 2000
    })
    
    return Promise.reject(error)
  }
  
  /**
   * 获取错误信息
   * @param {number} statusCode - HTTP状态码
   * @returns {string} 错误信息
   */
  getErrorMessage(statusCode) {
    const errorMessages = {
      400: '请求参数错误',
      401: '未授权,请重新登录',
      403: '拒绝访问',
      404: '请求资源不存在',
      500: '服务器内部错误',
      502: '网关错误',
      503: '服务不可用',
      504: '网关超时'
    }
    
    return errorMessages[statusCode] || '网络错误'
  }
}

// 创建实例
const requestUtils = new RequestUtils()

// 导出实例
export default requestUtils

// 导出便捷方法
export const { get, post, put, delete: del } = requestUtils

2.4.3 注释和文档规范

1. 代码注释规范

/**
 * 用户管理API
 * @module UserApi
 * @description 提供用户相关的API接口
 * @author 开发者姓名
 * @since 1.0.0
 */

/**
 * 用户信息接口
 * @typedef {Object} UserInfo
 * @property {string} id - 用户ID
 * @property {string} name - 用户姓名
 * @property {string} email - 邮箱地址
 * @property {string} avatar - 头像URL
 * @property {number} createTime - 创建时间戳
 */

class UserApi {
  /**
   * 获取用户信息
   * @async
   * @function getUserInfo
   * @param {string} userId - 用户ID
   * @returns {Promise<UserInfo>} 用户信息
   * @throws {Error} 当用户不存在时抛出错误
   * @example
   * // 获取用户信息
   * const userInfo = await UserApi.getUserInfo('123')
   * console.log(userInfo.name)
   */
  static async getUserInfo(userId) {
    // 参数验证
    if (!userId) {
      throw new Error('用户ID不能为空')
    }
    
    try {
      // 发送请求
      const response = await request.get(`/users/${userId}`)
      return response.data
    } catch (error) {
      // 错误处理
      console.error('获取用户信息失败:', error)
      throw error
    }
  }
  
  /**
   * 更新用户信息
   * @async
   * @function updateUserInfo
   * @param {string} userId - 用户ID
   * @param {Partial<UserInfo>} userInfo - 要更新的用户信息
   * @returns {Promise<UserInfo>} 更新后的用户信息
   * @example
   * // 更新用户姓名
   * const updatedUser = await UserApi.updateUserInfo('123', {
   *   name: '新姓名'
   * })
   */
  static async updateUserInfo(userId, userInfo) {
    // 实现代码...
  }
}

export default UserApi

2. README文档规范

# 项目名称

## 项目简介

简要描述项目的功能和特点。

## 技术栈

- UniApp 3.x
- Vue 3.x
- Vuex 4.x
- SCSS
- TypeScript (可选)

## 项目结构

s