ARCHITECTURE.md 6.8 KB

项目架构说明

页面结构

单页应用架构

项目采用单页面 + 组件切换的架构,实现类似原生TabBar的效果,同时保持头部和底部固定不变。

pages/
├── login/
│   └── login.vue           # 登录页面(独立页面)
└── index.vue               # 主容器页面(核心)

pages-content/              # 内容组件目录(独立)
├── home/
│   └── index.vue           # 首页内容组件
├── scan/
│   └── index.vue           # 扫描内容组件
└── my/
    └── index.vue           # 我的内容组件

主容器页面 (pages/index.vue)

结构组成

┌─────────────────────────────┐
│   自定义头部(固定)          │  ← 白色背景,显示当前标题
│   - 自适应状态栏高度         │     根据currentTab自动切换
├─────────────────────────────┤
│                             │
│   主内容区(动态切换)        │  ← 使用 v-if 切换组件
│   - HomePage 组件           │     - currentTab = 'home'
│   - ScanPage 组件           │     - currentTab = 'scan'
│   - MyPage 组件             │     - currentTab = 'mine'
│                             │
├─────────────────────────────┤
│   自定义底部导航栏(固定)    │  ← 白色背景,三个菜单
│   🏠 首页 | 📷 扫描 | 👤 我的 │     点击切换 currentTab
└─────────────────────────────┘

核心代码逻辑

// 当前激活的tab
const currentTab = ref('home')

// 切换tab - 只需要改变currentTab值
const switchTab = (name) => {
  if (currentTab.value === name) return
  currentTab.value = name
}

// 标题自动跟随当前tab
const currentPageTitle = computed(() => {
  const titles = {
    home: '首页',
    scan: '扫描',
    mine: '我的'
  }
  return titles[currentTab.value] || '首页'
})

组件切换

<view class="main-content">
  <!-- 通过 v-if 实现组件切换 -->
  <HomePage v-if="currentTab === 'home'" />
  <ScanPage v-else-if="currentTab === 'scan'" />
  <MyPage v-else-if="currentTab === 'mine'" />
</view>

内容组件

首页组件 (pages-content/home/index.vue)

<template>
  <view class="home-page">
    <view class="page-header">
      <text class="title">首页内容</text>
    </view>
    <view class="page-body">
      <text class="placeholder">首页主体内容区域</text>
    </view>
  </view>
</template>

特点

  • 纯内容组件,无头部和底部
  • 有自己的内部结构和样式
  • 可独立开发和维护

扫描组件 (pages-content/scan/index.vue)

<template>
  <view class="scan-page">
    <view class="page-header">
      <text class="title">扫描内容</text>
    </view>
    <view class="page-body">
      <text class="placeholder">扫描主体内容区域</text>
    </view>
  </view>
</template>

特点

  • 用于实现扫描相关功能
  • 可以调用相机API、扫码API等

我的组件 (pages-content/my/index.vue)

<template>
  <view class="my-page">
    <view class="page-header">
      <text class="title">我的内容</text>
    </view>
    <view class="page-body">
      <text class="placeholder">我的主体内容区域</text>
    </view>
  </view>
</template>

特点

  • 用于个人中心相关功能
  • 可以显示用户信息、设置等

页面跳转流程

登录成功后跳转

// pages/login/login.vue
uni.navigateTo({
  url: '/pages/index'  // 跳转到主容器页面
})

主容器内切换

// pages/index.vue
switchTab('scan')  // 切换到扫描页
// ↓
currentTab.value = 'scan'
// ↓
<ScanPage /> 组件显示
// ↓
头部标题变为"扫描"
// ↓
底部导航高亮"扫描"

架构优势

1. 性能优化

操作 重新渲染 说明
初始加载 完整渲染 加载主容器 + 首页组件
切换tab 只渲染内容 头部和底部不变
返回登录 完整渲染 卸载主容器

2. 开发便利

  • ✅ 每个内容组件独立开发
  • ✅ 头部和底部统一管理
  • ✅ 切换逻辑简单清晰
  • ✅ 易于维护和扩展

3. 用户体验

  • ✅ 切换流畅,无闪烁
  • ✅ 头部标题自动更新
  • ✅ 底部高亮自动切换
  • ✅ 类似原生TabBar体验

扩展指南

添加新的Tab页面

1. 创建内容组件

pages-content/newpage/index.vue

2. 在主容器中引入

<!-- pages/index.vue -->
<script setup>
import NewPage from '../pages-content/newpage/index.vue'
</script>

<template>
  <NewPage v-else-if="currentTab === 'newpage'" />
</template>

3. 添加底部导航配置

const tabList = ref([
  // ...现有配置
  {
    name: 'newpage',
    label: '新页面',
    icon: '🎯'
  }
])

4. 添加标题映射

const currentPageTitle = computed(() => {
  const titles = {
    // ...
    newpage: '新页面'
  }
  return titles[currentTab.value]
})

自定义头部

如果需要不同页面有不同的头部样式:

<!-- 方案1:使用 computed 动态样式 -->
<view 
  class="custom-header" 
  :style="{ 
    background: headerBackground,
    paddingTop: statusBarHeight + 'px' 
  }"
>
  <text>{{ currentPageTitle }}</text>
</view>

<script>
const headerBackground = computed(() => {
  const colors = {
    home: '#ffffff',
    scan: '#667eea',
    mine: '#ffffff'
  }
  return colors[currentTab.value]
})
</script>

组件通信

如果需要在内容组件间共享数据:

使用 Pinia Store

// store/tab.js
export const useTabStore = defineStore('tab', {
  state: () => ({
    sharedData: null
  })
})

// 在任意组件中使用
import { useTabStore } from '@/store/tab'
const tabStore = useTabStore()

配置文件

pages.json

{
  "pages": [
    {
      "path": "pages/login/login",
      "style": {
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/index",
      "style": {
        "navigationStyle": "custom"  // 使用自定义导航栏
      }
    }
  ]
}

注意

  • 不需要配置 tabBar
  • 所有tab功能都由 pages/index.vue 实现
  • pages-content/* 下的组件不需要在 pages.json 中注册

总结

这是一个轻量级、高性能的单页应用架构:

  • 🎯 简单 - 只有一个主页面 + 三个内容组件
  • 快速 - 切换tab只更新内容区域
  • 🎨 灵活 - 每个组件独立开发维护
  • 📦 可扩展 - 易于添加新的tab页面

适合需要底部导航的小程序项目!