6.1 核心内置组件
微信小程序提供了数十个内置组件,覆盖布局、表单、媒体、地图等场景。以下是最常用的几类:
view 与 scroll-view
<!-- scroll-view:可滚动区域,比 CSS overflow 更推荐 -->
<!-- 纵向滚动列表 -->
<scroll-view
scroll-y
style="height: 100vh;"
bindscrolltolower="onReachBottom"
refresher-enabled
refresher-triggered="{{refreshing}}"
bindrefresherrefresh="onRefresh"
>
<view wx:for="{{list}}" wx:key="id">{{item.name}}</view>
<view wx:if="{{loading}}">加载中...</view>
</scroll-view>
<!-- 横向滚动(标签栏)-->
<scroll-view scroll-x class="tab-scroll">
<view class="tab-list">
<view
wx:for="{{tabs}}"
wx:key="*this"
class="tab {{currentTab === index ? 'active' : ''}}"
bindtap="switchTab"
data-index="{{index}}"
>{{item}}</view>
</view>
</scroll-view>
swiper 轮播图
<swiper
class="banner"
autoplay
interval="{{3000}}"
duration="{{500}}"
circular
indicator-dots
indicator-color="rgba(255,255,255,.4)"
indicator-active-color="#ffffff"
bindchange="onBannerChange"
>
<swiper-item wx:for="{{banners}}" wx:key="id">
<image
src="{{item.image}}"
mode="aspectFill"
bindtap="onBannerTap"
data-url="{{item.link}}"
/>
</swiper-item>
</swiper>
image 组件的 mode 属性
aspectFill
等比缩放,短边充满,长边裁剪。适合商品封面图、头像等需要填满容器的场景(最常用)
aspectFit
等比缩放,长边充满,短边留白。适合展示完整图片内容,如商品详情图
widthFix
宽度固定,高度自动按比例。适合文章内图片,不需要设置高度
scaleToFill
拉伸填满(不保持比例),慎用,会变形
6.2 自定义组件开发
当内置组件无法满足需求,或多个页面复用同一 UI 逻辑时,需要创建自定义组件。
组件文件结构
components/product-card/
├── product-card.js # 组件逻辑
├── product-card.json # 声明这是组件
├── product-card.wxml # 组件模板
└── product-card.wxss # 组件样式(隔离)
// product-card.json — 声明为组件
{
"component": true,
"usingComponents": {}
}
完整自定义组件示例
// product-card.js
Component({
// 对外接口:接收父组件传入的数据
properties: {
product: {
type: Object,
value: {}
},
showBadge: {
type: Boolean,
value: false
},
size: {
type: String,
value: 'medium' // 'small' | 'medium' | 'large'
}
},
// 组件内部数据
data: {
isLiked: false
},
// 计算属性(Component 2.x 新增)
computed: {
discountText() {
const p = this.data.product
if (!p.originalPrice) return ''
return Math.round(p.price / p.originalPrice * 10) + '折'
}
},
// 生命周期
lifetimes: {
attached() {
// 组件被添加到页面节点树时
this.checkLikeStatus()
},
detached() {
// 组件从页面节点树移除时
}
},
// 所在页面的生命周期
pageLifetimes: {
show() {
// 页面显示时
},
hide() {
// 页面隐藏时
}
},
methods: {
onTap() {
// 触发自定义事件,通知父组件
this.triggerEvent('select', {
product: this.data.product
})
},
toggleLike(e) {
e.stopPropagation() // 阻止事件冒泡(组件方法中使用)
this.setData({ isLiked: !this.data.isLiked })
this.triggerEvent('like', {
productId: this.data.product.id,
liked: this.data.isLiked
})
},
async checkLikeStatus() {
// 检查是否已点赞
}
}
})
<!-- product-card.wxml -->
<view class="card card--{{size}}" bindtap="onTap">
<view class="cover-wrap">
<image class="cover" src="{{product.cover}}" mode="aspectFill"/>
<view wx:if="{{showBadge && product.isNew}}" class="badge">新品</view>
</view>
<view class="info">
<text class="name">{{product.name}}</text>
<view class="price-row">
<text class="price">¥{{product.price}}</text>
<text wx:if="{{discountText}}" class="discount">{{discountText}}</text>
</view>
</view>
<view class="like-btn {{isLiked ? 'liked' : ''}}" catchtap="toggleLike">
♥
</view>
</view>
父组件使用
<!-- 在页面或父组件 json 中注册 -->
// page.json
{
"usingComponents": {
"product-card": "/components/product-card/product-card"
}
}
<!-- 在 WXML 中使用 -->
<product-card
wx:for="{{products}}"
wx:key="id"
product="{{item}}"
show-badge
bindselect="onProductSelect"
bindlike="onProductLike"
/>
6.3 behaviors — 组件混入
behaviors 是小程序组件的混入机制,类似 Vue 的 mixins 或 React 的 HOC,用于在多个组件间共享逻辑。
// behaviors/loading.js — 定义一个通用的加载状态 behavior
module.exports = Behavior({
data: {
loading: false,
error: null
},
methods: {
startLoading() {
this.setData({ loading: true, error: null })
},
stopLoading() {
this.setData({ loading: false })
},
setError(msg) {
this.setData({ loading: false, error: msg })
},
async withLoading(fn) {
this.startLoading()
try {
return await fn()
} catch (e) {
this.setError(e.message)
throw e
} finally {
this.stopLoading()
}
}
}
})
// 在组件中使用 behavior
const loadingBehavior = require('../../behaviors/loading')
Component({
behaviors: [loadingBehavior],
methods: {
async fetchData() {
await this.withLoading(async () => {
const data = await api.getList()
this.setData({ list: data })
})
}
}
})
behaviors vs 自定义组件
behaviors 适合共享逻辑(数据+方法),不包含 UI 模板,类似工具函数的组合。自定义组件则包含完整的 WXML + WXSS + JS,共享 UI 结构。实际项目中二者结合使用效果最好。
6.4 Component 2.x(glass-easel)
Component 2.x 是 2024 年起推荐的新组件框架(通过 componentFramework: "glass-easel" 启用),提供更完整的响应式能力:
computed
计算属性,自动追踪依赖,依赖变化时重新计算,无需手动调用 setData
watch
侦听属性变化,支持深层监听(deep: true),替代 Component 1.x 的 observers
ref
在 WXML 中用 id 标记子组件,在父组件中通过 this.selectComponent 获取子组件实例并调用方法