4、小程序基础语法:WXML模板语法、WXSS样式语法、JS逻辑交互、数据绑定与渲染
好,咱们进入正题。小程序的基础语法,说白了就是三件套:WXML(结构)、WXSS(样式)、JS(逻辑)。再加上一个核心概念——数据绑定。这四个东西搞明白了,你就能写出一个能跑、能看、能交互的小程序了。
我记得刚接触小程序时,第一反应是:“这不就是HTML+CSS+JS吗?” 嗯,确实很像,但坑也不少。咱们一个一个说。
4.1 WXML:长得像HTML,但规矩更多
WXML 是微信定义的模板语言。它跟 HTML 最大的区别是:标签是微信自己封装的,比如 <view> 代替 <div>,<text> 代替 <span>。
我个人习惯把 WXML 理解为“带数据能力的 HTML”。它支持条件渲染、循环渲染,还能直接绑定 JS 里的数据。
核心语法示例:
<!-- 数据绑定 -->
<view>{{ message }}</view>
<!-- 条件渲染 -->
<view wx:if="{{ isShow }}">我出现了</view>
<!-- 循环渲染 -->
<view wx:for="{{ list }}" wx:key="id">
{{ item.name }}
</view>
这里有个坑,我曾经踩过:wx:key 必须写,否则列表更新时性能会崩。你想想看,如果列表有100项,没有 key 的话,小程序会全部重新渲染,那体验就太差了。
4.2 WXSS:CSS的“阉割版”+“增强版”
WXSS 大部分语法跟 CSS 一样,但有几个关键区别:
- 不支持通配符 *,所以不能写
* { margin: 0; }。我刚开始写的时候习惯性写了个*,结果样式全没生效,排查了半天。 - 新增了 rpx 单位,这是微信的响应式单位。简单说:1rpx = 屏幕宽度的 1/750。设计稿如果是 750px 宽,你直接写多少 px 就转成多少 rpx,省心。
- 支持 @import 导入样式,但注意路径要写相对路径。
我的建议:写样式时尽量用 rpx,别用 px。尤其是字体大小、边距、宽高,用 rpx 能保证在不同屏幕下比例一致。我在项目中遇到过用 px 写的按钮,在 iPhone 12 上正常,在 iPhone SE 上就挤成一团了。
4.3 JS逻辑交互:Page 函数是核心
小程序的 JS 逻辑,主要写在 Page() 函数里。每个页面都有一个对应的 JS 文件,里面定义数据、生命周期、事件处理等。
Page({
data: {
count: 0
},
// 生命周期
onLoad() {
console.log('页面加载了')
},
// 事件处理
handleTap() {
this.setData({
count: this.data.count + 1
})
}
})
这里有个关键点:修改数据必须用 this.setData(),不能直接 this.data.count = 1。为什么?因为 setData 会通知视图层更新,直接赋值只是改了内存里的值,页面不会变。
注意:setData 是异步的,而且频繁调用会影响性能。我曾经在一个循环里调了 100 次 setData,结果页面卡得动不了。后来改成一次性传一个对象,问题就解决了。
4.4 数据绑定与渲染:{{ }} 是桥梁
数据绑定是小程序最核心的机制。说白了,就是 JS 里的数据通过 {{ }} 传到 WXML 里,然后渲染出来。
举个例子:
// JS
Page({
data: {
user: {
name: '张三',
age: 25
},
isVip: true
}
})
// WXML
<view>姓名:{{ user.name }}</view>
<view>年龄:{{ user.age }}</view>
<view wx:if="{{ isVip }}">VIP 用户</view>
数据绑定支持表达式,比如 {{ user.age > 18 ? '成年' : '未成年' }}。但注意,不支持复杂的逻辑运算,比如函数调用、循环等。如果你需要复杂处理,建议在 JS 里先算好,再绑定。
避坑指南:我曾经在 {{ }} 里写了个 Math.random(),想生成随机数,结果发现每次渲染结果都一样。因为 WXML 里的表达式只在数据变化时重新计算,不会自动刷新。正确的做法是在 JS 里生成随机数,然后 setData 更新。
4.5 条件渲染 vs 隐藏渲染
小程序提供了两种控制元素显示的方式:
| 方式 | 语法 | 特点 |
|---|---|---|
| 条件渲染 | wx:if |
条件为 false 时,元素不渲染(DOM 中不存在) |
| 隐藏渲染 | hidden |
条件为 false 时,元素隐藏(display: none) |
怎么选?我的经验是:频繁切换用 hidden,一次性判断用 wx:if。比如一个弹窗,用户点开、关闭、再点开,用 hidden 更合适,因为不用反复创建和销毁 DOM。而像“是否显示用户头像”这种一次性的判断,用 wx:if 更省资源。
4.6 列表渲染:wx:for 的细节
列表渲染是 WXML 里最常用的功能之一。基本语法:
<view wx:for="{{ items }}" wx:for-item="item" wx:for-index="index" wx:key="id">
{{ index }} - {{ item.name }}
</view>
这里有几个细节:
wx:for-item可以自定义循环变量名,默认是itemwx:for-index可以自定义索引名,默认是index- wx:key 必须写,而且值最好是唯一标识,比如
id。如果列表是静态的,可以用*this表示用元素本身作为 key
小技巧:如果你在循环里嵌套循环,一定要给内层的 wx:for-item 和 wx:for-index 起不同的名字,否则会冲突。我见过有人内外都用 item,结果内层把外层的 item 覆盖了,数据全乱了。
4.7 事件绑定:bind 和 catch 的区别
小程序里绑定事件用 bind 或 catch,后面跟事件名,比如 bindtap、catchtap。
区别在于:
- bind:事件会冒泡(从子元素传到父元素)
- catch:事件不会冒泡(阻止传播)
举个例子:
<view bindtap="parentTap">
父元素
<view bindtap="childTap">子元素</view>
</view>
点击子元素时,会先触发 childTap,再触发 parentTap。如果你把子元素的 bindtap 改成 catchtap,那父元素的 parentTap 就不会触发了。
嗯,这里要注意:不要滥用 catch。我见过有人把所有事件都写成 catch,结果页面上的交互逻辑全乱了,因为该冒泡的事件没冒泡。
4.8 总结一下
小程序的基础语法,说白了就是:
- WXML 负责结构,用
{{ }}绑定数据 - WXSS 负责样式,用 rpx 做响应式
- JS 负责逻辑,用 setData 更新视图
- 数据绑定 是桥梁,把 JS 和 WXML 连起来
我个人觉得,学小程序语法最好的方式就是动手写。你打开开发者工具,新建一个页面,试着写一个列表、加一个点击事件、改一下样式。遇到问题就查文档,踩过坑就记住了。我当年就是这么过来的,现在回头看,那些坑其实都是财富。
下一章咱们聊聊小程序的生命周期,那可是个重头戏。准备好了吗?