4、小程序组件开发:基础组件、表单组件与导航组件
说实话,小程序开发里最核心的活儿,就是跟组件打交道。你想想看,用户看到的每一个按钮、每一段文字、每一张图片,本质上都是组件的堆叠。我刚开始带团队做电商小程序时,有个新人把 view 当 div 用,结果样式全乱套了——嗯,这里面的门道还真不少。
今天这一章,咱们就把小程序里最常用的三类组件掰开揉碎讲清楚。我会结合自己踩过的坑,帮你把基础打扎实。
4.1 基础组件:view、text、image、button
基础组件就像乐高积木里的基础块。你搭任何页面都离不开它们。
4.1.1 view——万能的容器
view 是小程序里最常用的组件,没有之一。它相当于 HTML 里的 div,但功能更纯粹——就是做布局容器。
核心要点:
- 默认是块级元素,独占一行
- 支持 flex 布局,配合
display: flex使用 - 可以嵌套任意组件
<!-- 一个典型的商品卡片布局 -->
<view class="product-card">
<view class="product-image">
<image src="{{product.img}}" />
</view>
<view class="product-info">
<text class="product-name">{{product.name}}</text>
<text class="product-price">¥{{product.price}}</text>
</view>
</view>
我个人习惯用 view 做所有区块的容器。但要注意,view 本身没有语义,别用它代替按钮或文本——那是其他组件的事。
小技巧: 给 view 加 hover-class 属性,可以实现点击态效果。比如商品列表项,加个 hover-class="item-hover",用户体验会好很多。
4.1.2 text——文本的正确打开方式
很多新手喜欢用 view 直接放文字,这其实不对。小程序里,文本内容应该用 text 组件包裹。
为什么?因为 text 支持文本选中、支持 decode 属性解码转义字符,而且性能更好。我在项目中遇到过一个问题:用 view 显示长文本时,在低端安卓机上会出现闪烁——换成 text 后问题就解决了。
<!-- text 组件的正确用法 -->
<text selectable="true">这段文字可以被用户选中复制</text>
<!-- 解码转义字符 -->
<text decode="true">价格:¥99.00 库存:<10件></text>
注意: text 组件只能嵌套 text,不能嵌套 view、image 等其他组件。我曾经看到有人把 image 塞进 text 里,结果图片死活不显示——嗯,这就是踩坑了。
4.1.3 image——图片加载有讲究
电商小程序里,图片是灵魂。但 image 组件有几个关键点你必须知道。
| 属性 | 说明 | 我的建议 |
|---|---|---|
src |
图片地址 | 尽量用 HTTPS,别用 HTTP |
mode |
裁剪/缩放模式 | 商品图用 aspectFill,详情图用 widthFix |
lazy-load |
懒加载 | 列表页一定要开,性能提升明显 |
show-menu-by-longpress |
长按识别二维码 | 看需求,不是必须的 |
<!-- 商品列表页的图片用法 -->
<image
src="{{item.thumb}}"
mode="aspectFill"
lazy-load="true"
style="width: 100%; height: 200rpx;"
/>
<!-- 商品详情页的大图 -->
<image
src="{{detail.banner}}"
mode="widthFix"
style="width: 100%;"
/>
我曾经在项目里犯过一个低级错误:商品列表的图片没开 lazy-load,结果一次性加载了 50 张图,页面卡得不行。后来加上懒加载,首屏速度提升了 40%。
4.1.4 button——不只是按钮
button 组件在小程序里很特殊。它不只是个按钮,还是很多能力的入口。
- 获取用户信息: 加
open-type="getUserInfo" - 获取手机号: 加
open-type="getPhoneNumber" - 分享: 加
open-type="share" - 打开客服: 加
open-type="contact"
<!-- 电商里最常用的几个按钮 -->
<button type="primary" size="default">立即购买</button>
<button type="default" size="mini">加入购物车</button>
<button open-type="contact">联系客服</button>
<button open-type="share">分享给好友</button>
避坑指南: 我曾经在 iOS 上遇到 button 的 border-radius 失效的问题。后来发现是 button 默认有 border 样式,需要先重置 border: none 再设置圆角。嗯,这个坑我记了很久。
4.2 表单组件:input、picker、switch
表单组件是用户和系统交互的桥梁。电商里,收货地址、商品筛选、设置偏好都离不开它们。
4.2.1 input——输入框的细节
input 看似简单,但坑不少。我总结几个关键点:
- 类型要明确: 数字键盘用
type="number",身份证用type="idcard" - 密码框: 用
password="true" - 占位符:
placeholder颜色可以自定义,用placeholder-style - 输入事件:
bindinput实时获取,bindblur失焦时获取
<!-- 收货地址表单 -->
<input
type="text"
placeholder="请输入收货人姓名"
placeholder-style="color: #999;"
bindinput="onNameInput"
/>
<input
type="number"
maxlength="11"
placeholder="请输入手机号"
bindinput="onPhoneInput"
/>
<input
type="text"
placeholder="请输入详细地址"
bindblur="onAddressBlur"
/>
注意: input 的 bindinput 事件返回的 event.detail.value 是实时值。如果你要做防抖处理(比如搜索框),记得用 setTimeout 控制频率。我见过有人直接拿实时值去请求接口,结果服务器被打爆了。
4.2.2 picker——选择器的妙用
picker 组件用来做选择,电商里最常见的场景就是选择商品规格(颜色、尺寸)。
| 模式 | 适用场景 | 示例 |
|---|---|---|
mode="selector" |
单选列表 | 选择性别、支付方式 |
mode="multiSelector" |
多列选择 | 选择省/市/区 |
mode="time" |
选择时间 | 选择配送时间 |
mode="date" |
选择日期 | 选择生日、预约日期 |
<!-- 商品规格选择 -->
<picker
mode="selector"
range="{{sizes}}"
bindchange="onSizeChange"
>
<view class="picker-display">
选择尺寸:{{selectedSize || '请选择'}}
</view>
</picker>
<!-- 省市区三级联动 -->
<picker
mode="multiSelector"
range="{{regions}}"
bindchange="onRegionChange"
bindcolumnchange="onColumnChange"
>
<view class="picker-display">
{{regionText || '请选择地区'}}
</view>
</picker>
我个人习惯在 picker 外面包一层 view,用来做样式美化。因为 picker 本身只提供选择功能,样式需要自己写。
4.2.3 switch——开关组件
switch 组件用来做二选一,比如是否默认地址、是否开启推送。
<!-- 设置默认地址 -->
<view class="switch-row">
<text>设为默认地址</text>
<switch
checked="{{isDefault}}"
color="#07c160"
bindchange="onDefaultChange"
/>
</view>
小技巧: switch 的 color 属性可以自定义开关颜色。电商里我一般用品牌色,比如绿色或橙色,视觉上更统一。
4.3 导航组件:navigator
小程序里页面跳转,navigator 是官方推荐的方式。它比 wx.navigateTo 更直观,而且支持声明式写法。
4.3.1 基本用法
<!-- 跳转到商品详情页 -->
<navigator url="/pages/detail/detail?id={{item.id}}">
<view class="product-item">
<image src="{{item.thumb}}" />
<text>{{item.name}}</text>
</view>
</navigator>
<!-- 跳转到 tabBar 页面 -->
<navigator url="/pages/cart/cart" open-type="switchTab">
<button>去购物车</button>
</navigator>
4.3.2 open-type 详解
| open-type | 说明 | 使用场景 |
|---|---|---|
navigate |
保留当前页,跳转新页 | 商品列表 → 商品详情 |
redirect |
关闭当前页,跳转新页 | 登录页 → 首页 |
switchTab |
跳转到 tabBar 页面 | 任意页 → 购物车 |
reLaunch |
关闭所有页,打开新页 | 退出登录 → 首页 |
navigateBack |
返回上一页 | 详情页 → 列表页 |
注意: 页面栈最多 10 层。如果你用 navigate 一直跳转,超过 10 层后页面会卡死。我建议在深层跳转时用 redirect 代替,或者用 reLaunch 重置页面栈。
4.3.3 传参技巧
通过 navigator 传参,参数会拼在 URL 后面。但要注意:
- 参数值要编码: 用
encodeURIComponent处理特殊字符 - 对象要序列化: 用
JSON.stringify转成字符串 - 接收时解码: 在目标页的
onLoad里用decodeURIComponent和JSON.parse
<!-- 传递复杂对象 -->
<navigator
url="/pages/detail/detail?product={{encodeURIComponent(JSON.stringify(item))}}">
<view>查看详情</view>
</navigator>
<!-- 接收参数 -->
// Page 的 onLoad 里
onLoad(options) {
const product = JSON.parse(decodeURIComponent(options.product));
this.setData({ product });
}
嗯,这里要提醒一下:别传太大的对象,URL 长度有限制。我一般只传 ID,然后在目标页重新请求数据——这样更安全,也更容易维护。
好了,这一章的内容就到这里。基础组件、表单组件、导航组件,这三类组件你掌握了,小程序页面开发的基本功就算打牢了。下一章我们会深入组件的自定义开发,到时候会更有意思。
本章小结:
view做容器,text放文字,image记得开懒加载button是能力入口,open-type要记牢- 表单组件注意类型和事件,
picker的多列选择有点绕 navigator跳转注意页面栈,传参要编码解码
公众号:蓝海资料掘金营,微信deep3321