3、小程序前端基础:WXML模板语法、WXSS样式布局、JS逻辑交互、Flex弹性布局实战
好,咱们进入第三章。这一章可以说是小程序开发的「地基工程」。你想想看,不管后面要做多复杂的电商系统,最终呈现给用户的,就是页面长什么样、交互顺不顺畅。说白了,就是 WXML、WXSS、JS 这三兄弟怎么配合干活。
我个人习惯,学新框架时先别急着写业务逻辑。先把模板语法摸透,把布局玩明白。不然写到后面,你会发现改个样式比写个接口还痛苦。嗯,我当年刚转小程序时,就吃过这个亏。
3.1 WXML 模板语法:小程序的「骨架」
WXML 长得像 HTML,但骨子里完全不一样。它不是真正的 DOM 标签,而是微信自己定义的一套标记语言。你写 <view>,它最终会被渲染成原生组件。
3.1.1 数据绑定
这是最基础,也是最常用的。用双花括号 {{ }} 把 JS 里的数据「塞」到模板里。
<!-- 页面显示:用户昵称:张三 -->
<view>用户昵称:{{nickName}}</view>
<!-- 属性绑定也支持 -->
<image src="{{avatarUrl}}"></image>
<!-- 还可以做简单运算 -->
<view>总价:{{price * count}} 元</view>
我在项目中遇到过一个问题:数据绑定时,如果某个字段是 undefined,页面会直接显示空字符串,不会报错。这其实是个坑,你调试时很难发现。所以我建议,所有从接口返回的数据,最好在 data 里先给个默认值。
3.1.2 条件渲染
用 wx:if 来控制元素显示隐藏。注意,它和 hidden 有本质区别。
<view wx:if="{{isVip}}">尊贵的VIP用户,欢迎您!</view>
<view wx:else>开通会员享受更多优惠</view>
<!-- 多个条件用 wx:elif -->
<view wx:if="{{score >= 90}}">优秀</view>
<view wx:elif="{{score >= 60}}">及格</view>
<view wx:else>继续努力</view>
wx:if 是「真条件渲染」,它会销毁和重建节点。如果频繁切换,性能开销大。而 hidden 只是控制 CSS 的 display,节点始终存在。我一般这样选:切换频率低用 wx:if,频率高用 hidden。
3.1.3 列表渲染
电商系统里,商品列表、订单列表,全得靠 wx:for。
<view wx:for="{{productList}}" wx:key="id">
<text>商品:{{item.name}} - ¥{{item.price}}</text>
</view>
<!-- 也可以自定义变量名 -->
<view wx:for="{{cartItems}}" wx:for-item="goods" wx:for-index="idx" wx:key="goodsId">
<text>第{{idx + 1}}件:{{goods.title}}</text>
</view>
wx:key 一定要加。不加的话,小程序会报警告,而且列表更新时性能会变差。我曾经因为偷懒没加 key,结果列表重新排序时,页面闪得跟幻灯片似的。
3.2 WXSS 样式布局:让页面「穿上衣服」
WXSS 和 CSS 基本一样,但多了个 rpx 单位。这个单位是微信专门为适配不同屏幕设计的。你写 750rpx,它就等于屏幕宽度。说白了,你按 iPhone 6 的 375px 设计稿来写,1px = 2rpx,换算起来非常方便。
3.2.1 选择器与样式导入
支持类选择器、ID 选择器、标签选择器。但注意,不支持通配符 *。
/* 外部样式文件,用 @import 导入 */
@import "common.wxss";
.container {
padding: 20rpx;
background-color: #f8f8f8;
}
#userAvatar {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
}
3.2.2 常用样式技巧
做电商页面,有几个样式我几乎天天用:
- 单行文本溢出省略:
overflow: hidden; white-space: nowrap; text-overflow: ellipsis; - 多行文本省略:
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; - 1px 边框(解决高清屏边框变粗):用伪元素 + transform 缩放
class,比如 .ellipsis、.border-bottom,放到一个 base.wxss 文件里。每个页面都导入它,省得重复写。
3.3 JS 逻辑交互:让页面「活起来」
JS 文件是页面的「大脑」。它负责处理数据、响应事件、调用 API。
3.3.1 页面生命周期
小程序页面有自己的一套生命周期。你只需要记住最常用的几个:
| 生命周期 | 触发时机 | 常用场景 |
|---|---|---|
onLoad |
页面加载时触发一次 | 获取页面参数、请求初始数据 |
onShow |
页面每次显示时触发 | 刷新购物车数量、恢复状态 |
onReady |
页面初次渲染完成 | 获取节点信息、开始动画 |
onPullDownRefresh |
用户下拉刷新 | 重新加载列表数据 |
onReachBottom |
页面触底 | 加载更多数据(分页) |
我一般把数据请求放在 onLoad 里。但如果是 tab 页面,切换回来需要刷新数据,那就得放 onShow 里。你想想看,用户从商品详情页返回列表页,如果列表不刷新,他刚买的商品还显示「可购买」,这不就出 bug 了吗?
3.3.2 事件绑定与传参
事件绑定用 bind 或 catch。区别在于 catch 会阻止事件冒泡。
<button bindtap="handleClick">点我</button>
<view catchtap="handleViewTap">点击我不会冒泡</view>
// JS 中定义事件处理函数
Page({
handleClick(e) {
console.log('按钮被点击了');
}
});
传参不能直接写在括号里,得用 data-* 自定义属性:
<view wx:for="{{list}}" wx:key="id">
<button bindtap="handleDelete" data-id="{{item.id}}">删除</button>
</view>
// 在事件中通过 e.currentTarget.dataset.id 获取
handleDelete(e) {
const id = e.currentTarget.dataset.id;
console.log('要删除的ID是:', id);
}
wx:for 里直接用 data-index="{{index}}" 传索引,结果列表增删后索引全乱了。后来我改用数据本身的唯一 ID 来传参,再通过 ID 去查找对应数据。这样更稳定。
3.4 Flex 弹性布局实战:电商页面「三板斧」
Flex 布局,说白了就是让元素「能屈能伸」。小程序里几乎所有页面布局,都能用 Flex 搞定。我总结了电商页面最常用的三种模式。
3.4.1 水平居中 + 垂直居中
比如商品卡片里的「加入购物车」按钮,要水平垂直居中。
.center-box {
display: flex;
justify-content: center;
align-items: center;
height: 100rpx;
}
3.4.2 两端对齐 + 垂直居中
商品列表里,左边是图片和名称,右边是价格和按钮。这种布局用 justify-content: space-between 最合适。
.product-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
}
.product-info {
display: flex;
align-items: center;
}
.product-price {
text-align: right;
}
3.4.3 等分排列(flex:1)
首页的分类导航,一行显示 4 个图标,每个占 1/4 宽度。
.nav-list {
display: flex;
}
.nav-item {
flex: 1;
text-align: center;
}
你想想看,如果不用 Flex,用浮动或者 inline-block,你得算宽度、清浮动、处理间距。用 Flex 一行代码就搞定了。我刚开始写小程序时,还习惯用 float,后来发现 Flex 真香,现在基本不用 float 了。
好了,这一章的内容就这些。WXML 是骨架,WXSS 是衣服,JS 是灵魂,Flex 是让它们协调工作的「胶水」。把这四个基础打牢,后面写电商页面就会非常顺手。下一章,咱们开始搭建项目结构,真正动手写代码了。