DEVELOPMENT-GUIDE.md 7.51 KB

开发指南

更新时间: 2026-02-05

本文档提供老来赛项目的开发规范和最佳实践。


🚀 快速开始

1. 环境准备

# 安装依赖
pnpm install

# 启动开发服务器
pnpm run dev:weapp

# 在微信开发者工具中打开 dist/ 目录

2. 开发流程

  1. 创建新页面

    # 在 src/pages/ 下创建页面目录
    mkdir src/pages/YourPage
    touch src/pages/YourPage/index.vue
    touch src/pages/YourPage/index.config.js
    
  2. 注册页面(必须):

    // src/app.config.js
    export default {
     pages: [
       // ... 其他页面
       'pages/YourPage/index'
     ]
    }
    
  3. 启动开发

    pnpm run dev:weapp
    

📝 代码规范

Vue 组件规范

✅ 推荐做法

<script setup>
import { ref, computed } from 'vue'

// 1. Props 定义(有类型和默认值)
const props = defineProps({
  userId: {
    type: Number,
    required: true
  },
  title: {
    type: String,
    default: ''
  }
})

// 2. Emits 定义(有事件名)
const emit = defineEmits(['update', 'delete'])

// 3. 响应式状态
const loading = ref(false)
const dataList = ref([])

// 4. 计算属性
const totalCount = computed(() => dataList.value.length)

// 5. 方法
const fetchData = async () => {
  loading.value = true
  try {
    const res = await yourAPI()
    if (res.code === 1) {
      dataList.value = res.data
    }
  } finally {
    loading.value = false
  }
}

// 6. 生命周期(使用 Taro Hooks)
import { useLoad, useShow } from '@tarojs/taro'

useLoad((options) => {
  // 页面加载(只触发一次)
  fetchData()
})

useShow(() => {
  // 页面显示(每次显示都触发)
})
</script>

<template>
  <view class="page-container">
    <!-- 模板内容 -->
  </view>
</template>

<style lang="less" scoped>
.page-container {
  padding: 30px;
}
</style>

❌ 避免做法

<script setup>
// ❌ 不要在页面中使用 Vue 生命周期
import { onMounted } from 'vue'
onMounted(() => {
  // 可能无法正常工作
})

// ❌ 不要直接修改 props
props.title = 'new title'

// ❌ 不要使用 Web API
localStorage.setItem('key', 'value')

API 调用规范

// ✅ 正确 - 检查 res.code === 1
const fetchData = async () => {
  try {
    const res = await yourAPI()
    if (res.code === 1) {  // 重要:检查 === 1
      // 处理成功
      console.log(res.data)
    } else {
      // 处理业务错误
      Taro.showToast({
        title: res.msg || '请求失败',
        icon: 'none'
      })
    }
  } catch (err) {
    // 处理网络错误
    console.error('请求失败:', err)
    Taro.showToast({
      title: '网络异常',
      icon: 'none'
    })
  }
}

// ❌ 错误 - 不检查或错误检查
const fetchData = async () => {
  const res = await yourAPI()
  if (res.code) {  // 错误:应该检查 === 1
    // ...
  }
}

路径别名使用

// ✅ 正确 - 使用路径别名
import { formatDate } from '@/utils/tools'
import UserCard from '@/components/UserCard.vue'
import { userAPI } from '@/api/user'

// ❌ 错误 - 使用相对路径
import { formatDate } from '../../utils/tools'
import UserCard from '../../components/UserCard.vue'

🎨 样式规范

TailwindCSS + Less 混合使用

<template>
  <!-- TailwindCSS 用于布局、间距、颜色(80%) -->
  <view class="flex flex-col gap-4 p-4 bg-white">
    <text class="text-xl font-bold text-gray-900">标题</text>
  </view>
</template>

<style lang="less" scoped>
/* Less 用于组件特定样式(20%) */
.custom-element {
  // 深度选择器修改第三方组件
  :deep(.nut-popup) {
    background-color: #fff;
  }

  // 复杂动画
  @keyframes slide-in {
    from { transform: translateX(-100%); }
    to { transform: translateX(0); }
  }
}
</style>

样式单位

// ✅ 正确 - 使用 px(Taro 自动转换为 rpx)
.container {
  width: 100px;   // → 100rpx
  height: 200px;
}

// ❌ 错误 - 直接写 rpx(除非明确需要)
.container {
  width: 100rpx;
}

🔧 常用模式

路由导航

import Taro from '@tarojs/taro'

// 跳转到新页面
Taro.navigateTo({
  url: '/pages/Detail/index?id=123'
})

// 重定向(无返回)
Taro.redirectTo({
  url: '/pages/Login/index'
})

// 切换 Tab
Taro.switchTab({
  url: '/pages/Dashboard/index'
})

// 返回上一页
Taro.navigateBack({
  delta: 1
})

获取路由参数

import { useLoad } from '@tarojs/taro'

useLoad((options) => {
  const { id, type } = options
  console.log('页面参数:', id, type)
})

本地存储

// 异步(推荐)
await Taro.setStorage({ key: 'user', data: userInfo })
const { data } = await Taro.getStorage({ key: 'user' })

// 同步(谨慎使用)
Taro.setStorageSync('token', 'xxxx')
const token = Taro.getStorageSync('token')

提示/弹窗

// Toast
Taro.showToast({
  title: '操作成功',
  icon: 'success',
  duration: 2000
})

// Modal
Taro.showModal({
  title: '提示',
  content: '确定删除吗?',
  success: (res) => {
    if (res.confirm) {
      // 用户点击确定
    }
  }
})

🧪 测试规范

单元测试(待添加)

// 示例:工具函数测试
import { describe, it, expect } from 'vitest'
import { formatDate } from '@/utils/tools'

describe('formatDate', () => {
  it('should format date correctly', () => {
    const result = formatDate('2026-02-05')
    expect(result).toBe('2026年02月05日')
  })
})

E2E 测试(待添加)

// 示例:关键流程测试
test('should login successfully', async ({ page }) => {
  await page.goto('/pages/login/index')
  await page.fill('input[name="phone"]', '13800138000')
  await page.click('button[type="submit"]')
  await expect(page).toHaveURL('/pages/dashboard/index')
})

📦 依赖管理

添加依赖

# 生产依赖
pnpm add package-name

# 开发依赖
pnpm add -D package-name

# NutUI 相关
pnpm add @nutui/nutui-taro

NutUI 组件使用

<template>
  <!-- ✅ 正确 - 自动导入,无需手动 import -->
  <nut-button type="primary">按钮</nut-button>
  <nut-popup v-model:visible="showPopup">
    内容
  </nut-popup>
</template>

<script setup>
// ❌ 错误 - 不要手动导入
// import { Button } from '@nutui/nutui-taro'
</script>

🚨 常见问题

Q1: 页面不显示?

检查清单

  • 页面是否在 app.config.js 中注册
  • 页面路径是否正确
  • 是否有语法错误

Q2: API 请求失败?

检查清单

  • 域名是否在微信小程序后台配置
  • sessionid 是否正确设置
  • 请求参数是否正确
  • 网络是否正常

Q3: 样式不生效?

检查清单

  • 是否添加了 scoped
  • 是否使用了不支持的 CSS
  • 是否被全局样式覆盖

Q4: 组件不显示?

检查清单

  • 组件名称是否正确(PascalCase)
  • NutUI 组件是否正确使用
  • 组件路径是否正确

📚 参考资源

项目文档

外部资源


维护者: 开发团队 最后更新: 2026-02-05