🧱 Taro 从零到一(三):页面与组件开发
系列导读:掌握了 React 基础,现在来认识 Taro 的内置组件体系。 小程序有自己的组件规范,Taro 将它们封装成了统一的 React 组件。
📊 Taro 内置组件 vs HTML
| Taro 组件 | HTML 等价 | 用途 |
|---|---|---|
<View> | <div> | 容器/块级元素 |
<Text> | <span> | 文本 |
<Image> | <img> | 图片 |
<Button> | <button> | 按钮 |
<Input> | <input> | 输入框 |
<Textarea> | <textarea> | 多行输入 |
<ScrollView> | <div style="overflow:scroll"> | 滚动视图 |
<Swiper> | 轮播库 | 轮播 |
<Navigator> | <a> | 导航链接 |
🔑 重要:在 Taro 中不能直接使用 HTML 标签! 必须从
@tarojs/components导入 Taro 组件。
📦 1. 常用组件详解
View — 万能容器
import { View, Text } from '@tarojs/components'
// View 就是 div 的替代品
<View className="container">
<View className="header">
<Text>标题</Text>
</View>
<View className="content">
<Text>内容</Text>
</View>
</View>
// 点击事件
<View className="clickable" onClick={() => console.log('点击了')}>
<Text>可点击的容器</Text>
</View>
Image — 图片
import { Image } from '@tarojs/components'
// 网络图片
<Image
src="https://example.com/photo.jpg"
mode="aspectFill" // 裁剪模式
lazyLoad // 懒加载
className="cover"
onError={() => console.log('加载失败')}
/>
// mode 属性对照
// aspectFill → CSS object-fit: cover (常用,裁剪填满)
// aspectFit → CSS object-fit: contain (完整显示,可能有留白)
// widthFix → 宽度固定,高度自适应 (适合商品图)
// scaleToFill → CSS object-fit: fill (拉伸填满,可能变形)
ScrollView — 滚动视图
import { ScrollView, View, Text } from '@tarojs/components'
// 纵向滚动列表
<ScrollView
scrollY // 纵向滚动
className="list"
style={{ height: '600px' }} // 必须设置固定高度
onScrollToLower={() => {
console.log('滚动到底部,加载更多')
loadMore()
}}
refresherEnabled // 开启下拉刷新
refresherTriggered={isRefreshing}
onRefresherRefresh={() => refresh()}
>
{items.map(item => (
<View key={item.id} className="item">
<Text>{item.name}</Text>
</View>
))}
</ScrollView>
// 横向滚动
<ScrollView scrollX className="horizontal-list">
{categories.map(cat => (
<View key={cat.id} className="category-item">
<Text>{cat.name}</Text>
</View>
))}
</ScrollView>
Swiper — 轮播
import { Swiper, SwiperItem, Image } from '@tarojs/components'
<Swiper
className="banner"
indicatorDots // 显示指示点
indicatorColor="rgba(255,255,255,0.5)"
indicatorActiveColor="#fff"
autoplay // 自动播放
interval={3000} // 切换间隔 3 秒
circular // 循环播放
>
{banners.map(banner => (
<SwiperItem key={banner.id}>
<Image src={banner.image} mode="aspectFill" className="banner-img" />
</SwiperItem>
))}
</Swiper>
🔄 2. 页面生命周期
import { useLoad, useReady, useDidShow, useDidHide, usePullDownRefresh, useReachBottom } from '@tarojs/taro'
function ListPage() {
// 页面加载(类似 onLoad)
useLoad((options) => {
console.log('页面加载,参数:', options)
// options 包含页面跳转传递的参数
// 例如 /pages/detail/index?id=123 → options.id = '123'
})
// 页面初次渲染完成
useReady(() => {
console.log('页面渲染完成')
})
// 页面显示(每次切回来都会触发)
useDidShow(() => {
console.log('页面显示,刷新数据')
})
// 页面隐藏
useDidHide(() => {
console.log('页面隐藏')
})
// 下拉刷新
usePullDownRefresh(async () => {
await fetchData()
Taro.stopPullDownRefresh() // 停止刷新动画
})
// 触底加载更多
useReachBottom(() => {
console.log('到底了,加载更多')
loadMore()
})
return <View>列表页</View>
}
页面配置开启下拉刷新
// pages/list/index.config.ts
export default definePageConfig({
navigationBarTitleText: '列表',
enablePullDownRefresh: true, // 开启下拉刷新
onReachBottomDistance: 100, // 触底距离(px)
})
🏗 3. 自定义组件最佳实践
商品卡片组件
// src/components/ProductCard/index.tsx
import { View, Text, Image } from '@tarojs/components'
import './index.scss'
interface ProductCardProps {
product: {
id: string
name: string
price: number
image: string
sales: number
}
onTap?: (id: string) => void
}
export default function ProductCard({ product, onTap }: ProductCardProps) {
return (
<View className="product-card" onClick={() => onTap?.(product.id)}>
<Image className="product-image" src={product.image} mode="aspectFill" />
<View className="product-info">
<Text className="product-name">{product.name}</Text>
<View className="product-bottom">
<Text className="product-price">
<Text className="price-symbol">¥</Text>
{product.price}
</Text>
<Text className="product-sales">已售 {product.sales}</Text>
</View>
</View>
</View>
)
}
// src/components/ProductCard/index.scss
.product-card {
display: flex;
flex-direction: column;
background: #fff;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
.product-image {
width: 100%;
height: 320px;
}
.product-info {
padding: 16px;
.product-name {
font-size: 28px;
color: #1a1a1a;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.product-bottom {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 12px;
.product-price {
font-size: 36px;
font-weight: bold;
color: #ef4444;
.price-symbol { font-size: 24px; }
}
.product-sales {
font-size: 22px;
color: #999;
}
}
}
}
✅ 本篇小结 Checklist
- 掌握 View / Text / Image / Button 基础组件
- 会用 ScrollView 做滚动列表(含下拉刷新、触底加载)
- 会用 Swiper 做轮播图
- 掌握页面生命周期 Hook(useLoad / useDidShow 等)
- 能独立封装可复用组件
下一篇预告:《路由与页面导航》
本文是「Taro 从零到一」系列第 3 篇,共 10 篇。