02-React+TypeScript基础速览

⚛️ Taro 从零到一(二):React + TypeScript 基础速览

系列导读:Taro 以 React 为核心框架,如果你还不太熟悉 React 和 TypeScript, 本文帮你快速掌握 Taro 开发所需的全部基础。


🧩 1. JSX --- 在 JS 中写 HTML

tsx 复制代码
// JSX = JavaScript + XML,让你在 JS 中写 UI
function Welcome() {
  const name = '张三'
  const isVip = true

  return (
    <View className="welcome">
      {/* 文本插值 */}
      <Text>你好,{name}!</Text>

      {/* 条件渲染 */}
      {isVip && <Text className="vip-badge">VIP</Text>}

      {/* 三元表达式 */}
      <Text>{isVip ? '尊贵会员' : '普通用户'}</Text>
    </View>
  )
}

列表渲染

tsx 复制代码
function UserList() {
  const users = [
    { id: 1, name: '张三', age: 25 },
    { id: 2, name: '李四', age: 30 },
    { id: 3, name: '王五', age: 28 },
  ]

  return (
    <View>
      {users.map(user => (
        <View key={user.id} className="user-card">
          <Text>{user.name}</Text>
          <Text>{user.age} 岁</Text>
        </View>
      ))}
    </View>
  )
}

🔄 2. useState --- 状态管理

tsx 复制代码
import { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)          // 数字状态
  const [name, setName] = useState('')           // 字符串状态
  const [items, setItems] = useState<string[]>([]) // 数组状态

  return (
    <View>
      {/* 数字 */}
      <Text>{count}</Text>
      <Button onClick={() => setCount(count + 1)}>+1</Button>
      <Button onClick={() => setCount(prev => prev - 1)}>-1</Button>

      {/* 数组 */}
      <Button onClick={() => setItems([...items, `Item ${items.length + 1}`])}>
        添加
      </Button>
      {items.map((item, i) => (
        <Text key={i}>{item}</Text>
      ))}
    </View>
  )
}

⚡ 3. useEffect --- 副作用

tsx 复制代码
import { useState, useEffect } from 'react'

function UserProfile() {
  const [user, setUser] = useState(null)
  const [loading, setLoading] = useState(true)

  // 组件挂载时获取数据
  useEffect(() => {
    async function fetchUser() {
      setLoading(true)
      const res = await Taro.request({ url: 'https://api.example.com/user' })
      setUser(res.data)
      setLoading(false)
    }
    fetchUser()
  }, [])  // 空数组 = 只在挂载时执行一次

  if (loading) return <Text>加载中...</Text>

  return <Text>{user?.name}</Text>
}

useEffect 依赖规则

tsx 复制代码
// ① 空数组 --- 只执行一次(挂载时)
useEffect(() => { /* 初始化 */ }, [])

// ② 有依赖 --- 依赖变化时执行
useEffect(() => { /* keyword 变化时重新搜索 */ }, [keyword])

// ③ 清理函数 --- 组件卸载时执行
useEffect(() => {
  const timer = setInterval(() => console.log('tick'), 1000)
  return () => clearInterval(timer)  // 清理定时器
}, [])

🧱 4. 组件与 Props

tsx 复制代码
// 定义 Props 类型
interface ProductCardProps {
  name: string
  price: number
  image: string
  onBuy?: () => void   // 可选回调
}

// 函数组件
function ProductCard({ name, price, image, onBuy }: ProductCardProps) {
  return (
    <View className="product-card">
      <Image src={image} mode="aspectFill" />
      <Text className="name">{name}</Text>
      <Text className="price">¥{price.toFixed(2)}</Text>
      {onBuy && <Button onClick={onBuy}>购买</Button>}
    </View>
  )
}

// 使用组件
function ProductList() {
  return (
    <View>
      <ProductCard
        name="Flutter 实战"
        price={59}
        image="/assets/book.png"
        onBuy={() => Taro.showToast({ title: '已加入购物车' })}
      />
    </View>
  )
}

🪝 5. 自定义 Hook

tsx 复制代码
// 封装通用逻辑
function useToggle(initial = false) {
  const [value, setValue] = useState(initial)
  const toggle = useCallback(() => setValue(v => !v), [])
  const setTrue = useCallback(() => setValue(true), [])
  const setFalse = useCallback(() => setValue(false), [])
  return { value, toggle, setTrue, setFalse }
}

// 使用
function PasswordInput() {
  const { value: visible, toggle } = useToggle(false)

  return (
    <View>
      <Input type={visible ? 'text' : 'password'} placeholder="请输入密码" />
      <Button onClick={toggle}>{visible ? '隐藏' : '显示'}</Button>
    </View>
  )
}
tsx 复制代码
// 通用请求 Hook
function useRequest<T>(fetcher: () => Promise<T>) {
  const [data, setData] = useState<T | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<Error | null>(null)

  const run = useCallback(async () => {
    setLoading(true)
    setError(null)
    try {
      const result = await fetcher()
      setData(result)
    } catch (e) {
      setError(e as Error)
    } finally {
      setLoading(false)
    }
  }, [fetcher])

  useEffect(() => { run() }, [run])

  return { data, loading, error, refresh: run }
}

// 使用
function ProductPage() {
  const { data: products, loading, refresh } = useRequest(() =>
    fetchProducts()
  )

  if (loading) return <Text>加载中...</Text>
  return (
    <View>
      {products?.map(p => <ProductCard key={p.id} {...p} />)}
    </View>
  )
}

📝 6. TypeScript 在 Taro 中的最佳实践

typescript 复制代码
// 接口定义
interface User {
  id: string
  name: string
  avatar: string
  age?: number           // 可选属性
}

// API 响应类型
interface ApiResponse<T> {
  code: number
  message: string
  data: T
}

// 使用泛型
async function fetchApi<T>(url: string): Promise<T> {
  const res = await Taro.request<ApiResponse<T>>({ url })
  if (res.data.code !== 0) {
    throw new Error(res.data.message)
  }
  return res.data.data
}

// 调用
const users = await fetchApi<User[]>('/api/users')
const user = await fetchApi<User>('/api/user/123')

常用类型工具

typescript 复制代码
// Partial --- 所有属性变可选
type UserUpdate = Partial<User>  // { id?: string, name?: string, ... }

// Pick --- 选取部分属性
type UserBrief = Pick<User, 'id' | 'name'>  // { id: string, name: string }

// Omit --- 排除部分属性
type NewUser = Omit<User, 'id'>  // { name: string, avatar: string, age?: number }

// Record --- 键值对映射
type UserMap = Record<string, User>  // { [key: string]: User }

✅ 本篇小结 Checklist

  • 掌握 JSX 语法(插值、条件渲染、列表渲染)
  • 掌握 useState 状态管理
  • 理解 useEffect 副作用和依赖规则
  • 会定义组件 Props 类型
  • 掌握自定义 Hook 封装
  • 了解 TypeScript 泛型和类型工具

下一篇预告:《页面与组件开发》------ 学习 Taro 内置组件体系和页面生命周期。


本文是「Taro 从零到一」系列第 2 篇,共 10 篇。

相关推荐
新晨4371 小时前
Git跨分支文件恢复:如何将其他分支的内容安全拷贝到当前分支
前端·git
踩着两条虫2 小时前
VTJ.PRO 在线应用开发平台入门与项目初始化
前端·人工智能·ai编程
流星雨在线2 小时前
大前端通用性能优化(高频场景专项)
前端·性能优化
方安乐2 小时前
ESLint代码规范(一)
前端·javascript·代码规范
酉鬼女又兒2 小时前
零基础快速入门前端JavaScript Array 常用方法详解与实战(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·javascript·chrome·蓝桥杯
January12072 小时前
Vue3打卡计时器:完整实现与优化方案
前端·javascript·css
GISer_Jing2 小时前
React全解析:从入门到精通实战指南
前端·react.js·前端框架
happymaker06262 小时前
web前端学习日记——DAY07(js交互编程)
前端·javascript·学习
lizi662 小时前
uniapp uview-plus 自定义动态验证
前端·vue.js·微信小程序