Files
school2-taro/CLAUDE.md
T
2026-07-13 14:44:13 +08:00

7.7 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build & Development

# WeChat mini-program
npm run dev:weapp          # Watch/dev build → weapp/
npm run build:weapp        # Production build → weapp/

# H5 (web)
npm run dev:h5             # Watch/dev build → build/
npm run build:h5           # Production build → build/

Output directories are determined by TARO_ENV: for H5 it's build/, for all other platforms it matches the platform name (e.g., weapp/).

No test or lint scripts are configured. ESLint (eslint-config-taro) and Stylelint are installed but must be run manually.

Architecture

This is a Taro 3.6 cross-platform app using React 18 (concurrent mode), TypeScript, and Webpack 5. It targets WeChat, Alipay, DingTalk, JD, Kwai, QQ, Baidu, Toutiao mini-programs, and H5 web.

UI Library: @antmjs/vantui

The UI library is @antmjs/vantui (v3), a Taro-compatible port of Vant. Components are imported from @antmjs/vantui directly (e.g., import { Button } from '@antmjs/vantui'). The babel-plugin-import in babel.config.js handles on-demand style imports.

Page Structure

Each page lives in src/pages/<name>/ and consists of three files:

  • index.tsx — page component (functional or class)
  • index.config.ts — page-level config (title, navigation style, etc.)
  • index.less — page styles

Pages must be registered in src/app.config.ts under the pages array.

Path Alias

@ maps to src/ (configured in config/index.js).

Theme & Global Styles

  • src/app.less — global app styles (imported in app.ts)
  • src/styles/index.less — theme variable overrides for Vant UI. It imports @antmjs/vantui/es/style/var.less and uncomments/redefines Less variables to customize the theme. This file is injected into every .less file via Less modifyVars (configured in config/index.js under both mini.lessLoaderOption and h5.lessLoaderOption).

Webpack Customizations (config/webpack/)

  • commonChain.js — Overrides Taro's default script rule exclude so that Babel also processes these node_modules packages: taro, inversify, @antmjs, react-spring, recoil, buffer, qrcode. Do NOT include "taro" in the project name or all node_modules will be recompiled.
  • miniChain.js — Applied to mini-program builds. Adds:
    • MiniFixPlugin — fixes path param encoding differences between WeChat/Douyin and Alipay/DingTalk
    • GlobalFixPlugin — polyfills the global variable for Alipay, DingTalk, and Baidu mini-programs
  • h5Chain.js — Applied to H5 builds. Adds H5FixPlugin for H5 compatibility fixes.

Build Config Layers

config/index.js exports a function that merges the base config with config/development.js or config/production.js based on NODE_ENV. Environment variables:

Variable Purpose Default
TARO_ENV Target platform (weapp, h5, alipay, etc.) weapp
NODE_ENV Build mode production
API_ENV API environment selector real
  • designWidth: 750 — all px values are converted to rpx at this ratio
  • @tarojs/plugin-framework-react is configured with reactMode: "concurrent" (React 18 concurrent features)
  • browserslist targets iOS 9+ for production

App Entry

  • src/app.ts — class-based App component, renders this.props.children (the current page)
  • src/app.config.ts — defines routes (pages array), window config, and app-level settings
  • src/index.html — H5 entry HTML template

VantUI Component API Reference (v3.7)

This project uses @antmjs/vantui v3.7. The official docs: https://antmjs.github.io/vantui/main/

Always check the actual type definitions in node_modules/@antmjs/vantui/types/ when unsure about props. Key API notes for commonly used components:

  • shape: 'square' (default) | 'round'
  • background: background color string (default #FFFFFF)
  • onFocus, onBlur, onChange, onSearch, onClear, onCancel — event callbacks
  • leftIcon, rightIcon — icon name or image URL
  • showAction + actionText — right-side action button

Swiper (NOT the same as Taro's native Swiper)

  • autoPlay — auto-play interval in ms (0 = disabled). Not autoplay
  • loop — infinite loop mode. Not circular
  • paginationColor — indicator dot color. Not indicatorColor
  • paginationVisible — show/hide pagination dots
  • duration — animation duration (default 500)
  • width / height — card dimensions
  • No indicatorActiveColor prop — only one paginationColor
  • onChange callback: (currPage: number) => void (not an event object)

SwiperItem

  • Minimal component, only className and children. No special props.

Grid / GridItem

  • Grid: columnNum, border, gutter, square, clickable, center, iconSize
  • GridItem: icon (string), text (ReactNode), iconColor, dot, info/badge, url + linkType

Tabs / Tab (v3.7)

  • Tabs:
    • active — current tab index (number | string)
    • sticky — enable sticky mode
    • offsetTop — sticky offset in px. Not stickyOffsetTop
    • color, titleActiveColor, titleInactiveColor — color props
    • type: 'line' | 'card'
    • swipeable — enable swipe gesture switching
    • animated — enable tab switch animation
    • ellipsis — text overflow ellipsis (default true)
    • No lineWidth or lineHeight props
    • onChange: (e: { detail: { index: number; name?: string; title?: string } }) => void
  • Tab: title (ReactNode), name (identifier), dot, info, disabled, titleStyle

Image (VantUI Image, not Taro's native Image)

  • src, fit ('contain' | 'cover' | 'fill' | 'widthFix' | 'heightFix' | 'none'), width, height, radius
  • round — circular image (boolean)
  • lazyLoad, showError, showLoading
  • renderLoading, renderError — custom render slots

Common VantUI pattern: Taro's native components vs VantUI components

  • Use @tarojs/components for: View, Text, ScrollView, Image (native, simpler)
  • Use @antmjs/vantui for: styled UI components (Search, Swiper, Tabs, Grid, Button, etc.)
  • VantUI component props extend Taro's ViewProps, so onClick/onTap and style props are always available

Custom TabBar (src/custom-tab-bar/)

This project uses Taro's custom tabBar mechanism (tabBar.custom: true in app.config.ts). Key rules:

Component location

  • The custom tabBar component MUST be at src/custom-tab-bar/index.tsx — this is a Taro convention, not configurable
  • Taro automatically renders this component on every tab page; do NOT import <CustomTabBar /> in individual pages

Do NOT use CoverView

  • CoverView / CoverImage have known bugs on real devices: invisible, click events don't bubble
  • Use regular <View> with position: fixed; bottom: 0; z-index: 999 instead

Active tab state

  • Taro creates a new instance of the tabBar component on each page, so useState resets on every tab switch
  • Derive the active tab from Taro.getCurrentPages() at render time — NOT from component state
  • Pattern: const route = Taro.getCurrentPages()[last]?.route; const activeKey = TAB_LIST.find(t => route.includes(t.key))

Tab switching

  • Use Taro.switchTab({ url: pagePath }) — this matches native tabBar behavior
  • The pagePath format must match the tabBar.list[].pagePath in app.config.ts

Center "publish" button

  • The publish button is a UI-only element not in tabBar.list
  • It triggers a VantUI <Popup> rendered as a sibling of the tabBar, NOT nested inside it
  • The popup state can use useState since it's ephemeral and not shared across tabs