bookworm-smart-assistant/skills/miniprogram-expert/references/taro-guide.md

3.8 KiB

Taro 跨端开发指南

函数组件 + Hooks

import { View, Text, Button } from '@tarojs/components'
import { useLoad, useDidShow, useShareAppMessage } from '@tarojs/taro'
import { useState, useCallback } from 'react'
import './index.scss'

const Index: React.FC = () => {
  const [list, setList] = useState<Item[]>([])
  const [loading, setLoading] = useState(false)

  useLoad((options) => {
    console.log('参数:', options)
    fetchData()
  })

  useDidShow(() => { /* 每次显示 */ })

  useShareAppMessage(() => ({
    title: '分享',
    path: '/pages/index/index'
  }))

  const fetchData = useCallback(async () => {
    setLoading(true)
    try {
      const res = await api.getList()
      setList(res.data)
    } finally {
      setLoading(false)
    }
  }, [])

  return (
    <View className='index'>
      {list.map(item => (
        <View key={item.id} onClick={() => handleClick(item.id)}>
          <Text>{item.name}</Text>
        </View>
      ))}
    </View>
  )
}

export default Index

页面配置

// index.config.ts
export default definePageConfig({
  navigationBarTitleText: '首页',
  enablePullDownRefresh: true
})

常用 Hooks

import Taro, {
  useLoad,           // onLoad
  useReady,          // onReady
  useDidShow,        // onShow
  useDidHide,        // onHide
  useUnload,         // onUnload
  usePullDownRefresh,
  useReachBottom,
  useShareAppMessage,
  useShareTimeline,
  useRouter          // 获取路由参数
} from '@tarojs/taro'

// 路由参数
const { params } = useRouter()
console.log(params.id)

// 下拉刷新
usePullDownRefresh(() => {
  fetchData().then(() => Taro.stopPullDownRefresh())
})

API 调用

// 统一 API
Taro.request({ url, data, method })
Taro.navigateTo({ url: '/pages/detail/detail?id=1' })
Taro.showToast({ title: '成功', icon: 'success' })
Taro.setStorageSync('key', value)
Taro.getStorageSync('key')

// 环境判断
if (process.env.TARO_ENV === 'weapp') { /* 微信 */ }
if (process.env.TARO_ENV === 'alipay') { /* 支付宝 */ }
if (process.env.TARO_ENV === 'h5') { /* H5 */ }

状态管理 (Zustand)

// store/user.ts
import { create } from 'zustand'

interface UserStore {
  user: User | null
  setUser: (user: User) => void
  logout: () => void
}

export const useUserStore = create<UserStore>(set => ({
  user: null,
  setUser: (user) => set({ user }),
  logout: () => set({ user: null })
}))

// 使用
const { user, setUser } = useUserStore()

请求封装

// services/request.ts
import Taro from '@tarojs/taro'

const BASE_URL = 'https://api.example.com'

export const request = async <T>(options: Taro.request.Option): Promise<T> => {
  const token = Taro.getStorageSync('token')
  
  const res = await Taro.request({
    ...options,
    url: BASE_URL + options.url,
    header: {
      'Authorization': token ? `Bearer ${token}` : '',
      ...options.header
    }
  })
  
  if (res.statusCode === 401) {
    Taro.removeStorageSync('token')
    Taro.navigateTo({ url: '/pages/login/login' })
    throw new Error('未授权')
  }
  
  if (res.data.code !== 0) {
    Taro.showToast({ title: res.data.message, icon: 'none' })
    throw new Error(res.data.message)
  }
  
  return res.data.data
}

export const get = <T>(url: string, data?: any) => 
  request<T>({ url, method: 'GET', data })

export const post = <T>(url: string, data?: any) => 
  request<T>({ url, method: 'POST', data })

样式

// 使用 rpx 或 Taro 默认转换 px
.container {
  padding: 20px;  // 会自动转换
  font-size: 28px;
}

// 条件编译
/* #ifdef weapp */
.weapp-only { }
/* #endif */

条件编译

// JS 条件编译
/* @conditional-compile {"mp-weapp": true} */
console.log('只在微信小程序')

// JSX 条件编译
{process.env.TARO_ENV === 'weapp' && <WxComponent />}