Chapter 03

WXML 模板语法

掌握数据绑定、条件渲染、列表渲染与模板复用,理解 WXML 与 HTML 的核心差异

3.1 WXML 是什么

WXML(WeiXin Markup Language)是微信小程序的模板语言,语法上类似 HTML,但有本质区别。WXML 不运行在浏览器中,没有 DOM 概念,所有标签都是小程序框架定义的组件。

WXML 有

  • 数据绑定 {{变量}}
  • 条件渲染 wx:if
  • 列表渲染 wx:for
  • 模板复用 template
  • 事件绑定 bind*/catch*
  • 引用 import/include

WXML 没有

  • div/span/p 等 HTML 标签
  • DOM API(document、window)
  • script 标签(逻辑在 .js 中)
  • link/style 标签(样式在 .wxss 中)
  • HTML 全局属性(如 id 用于 CSS)

3.2 数据绑定

WXML 使用 {{expression}} 语法将 Page.data 中的数据绑定到模板,支持表达式运算、对象属性访问和方法调用(有限制)。

基础数据绑定

<!-- index.wxml -->

<!-- 绑定文本内容 -->
<view>{{message}}</view>
<text>你好,{{userInfo.nickname}}</text>

<!-- 绑定属性值(必须在引号内使用 {{}})-->
<image src="{{avatarUrl}}" mode="aspectFill"/>

<!-- 绑定布尔属性(注意:不能直接写 checked,要用 {{}} )-->
<checkbox checked="{{isChecked}}"/>

<!-- 表达式运算 -->
<view>总价:{{price * quantity}}</view>
<view>{{isVip ? '会员价' : '普通价'}}</view>
<view>{{index + 1}}. {{item.name}}</view>

<!-- 字符串拼接 -->
<view class="item {{active ? 'active' : ''}}">选项</view>
// index.js — 对应的 data
Page({
  data: {
    message: 'Hello, 小程序',
    userInfo: { nickname: '张三', avatar: '' },
    avatarUrl: 'https://example.com/avatar.jpg',
    isChecked: true,
    price: 99.9,
    quantity: 3,
    isVip: false,
    active: true
  }
})
⚠️
{{}} 内的限制

WXML 的 {{}} 内只支持简单 JavaScript 表达式,不能调用自定义函数(如 {{formatDate(date)}} 是无效的)。需要格式化数据时,应在 setData 之前处理好再存入 data,或使用 WXS 模块。

3.3 条件渲染

WXML 提供两种条件渲染机制,适用于不同场景:

wx:if / wx:elif / wx:else

<!-- 完整的条件分支 -->
<view wx:if="{{orderStatus === 'pending'}}">待付款</view>
<view wx:elif="{{orderStatus === 'paid'}}">已付款</view>
<view wx:elif="{{orderStatus === 'shipped'}}">已发货</view>
<view wx:else>已完成</view>

<!-- block 包裹多个元素(不产生额外节点)-->
<block wx:if="{{isLogin}}">
  <view>用户名:{{username}}</view>
  <view>积分:{{points}}</view>
</block>
<block wx:else>
  <button bindtap="goLogin">立即登录</button>
</block>

hidden 属性 vs wx:if

<!-- hidden 只是隐藏(display:none),元素仍然存在 -->
<view hidden="{{!showPanel}}">侧边面板</view>

<!-- wx:if 为 false 时,节点完全不创建 -->
<view wx:if="{{showModal}}">弹窗内容</view>
对比维度wx:ifhidden
DOM 节点false 时节点不存在始终存在,只改变 display
性能(频繁切换)较差(销毁/重建开销)较好(只改样式)
性能(不频繁切换)较好(false 时无渲染开销)较差(始终占用内存)
子组件生命周期会触发 attached/detached不触发生命周期
适用场景切换不频繁的大块内容高频切换的简单元素

3.4 列表渲染

列表渲染是小程序开发中最常用的特性,用于将数组数据渲染为重复的 UI 结构。

基础 wx:for 用法

<!-- 默认:item 为数组元素,index 为下标 -->
<view wx:for="{{products}}" wx:key="id">
  <text>{{index + 1}}. {{item.name}}</text>
  <text>¥{{item.price}}</text>
</view>

<!-- 自定义变量名(推荐,代码更清晰)-->
<view
  wx:for="{{cartItems}}"
  wx:for-item="product"
  wx:for-index="i"
  wx:key="productId"
>
  <text>{{i + 1}}. {{product.name}} × {{product.quantity}}</text>
</view>

<!-- 嵌套列表(分类+商品)-->
<view wx:for="{{categories}}" wx:for-item="cate" wx:key="cateId">
  <text class="cate-title">{{cate.name}}</text>
  <view
    wx:for="{{cate.items}}"
    wx:for-item="goods"
    wx:key="goodsId"
  >
    <text>{{goods.name}}</text>
  </view>
</view>

wx:key 的重要性

🔴
务必设置 wx:key

wx:key 告诉框架列表中每个节点的唯一标识,当列表数据变化(增删排序)时,框架可以复用已有节点而不是全部重新渲染,大幅提升性能。设置规则:
wx:key="id" — item 的属性名(最推荐)
wx:key="*this" — item 本身(适用于字符串/数字数组)
不设置 — 控制台警告,且列表性能差

3.5 模板(template)复用

当多个页面需要重复相同的 UI 片段时,可以用 template 定义可复用的模板。注意:template 只共享 WXML 结构,创建独立的作用域(与自定义组件不同)。

定义和使用模板

<!-- templates/product-item.wxml -->
<template name="productItem">
  <view class="product-card">
    <image src="{{cover}}" mode="aspectFill"/>
    <view class="info">
      <text class="name">{{name}}</text>
      <text class="price">¥{{price}}</text>
    </view>
  </view>
</template>

<!-- index.wxml — 使用模板 -->
<!-- 第一步:import 引入模板文件 -->
<import src="../../templates/product-item.wxml"/>

<!-- 第二步:is 指定模板名,data 传入数据 -->
<template
  is="productItem"
  data="{{...item}}"
/>

<!-- 批量渲染 -->
<view wx:for="{{products}}" wx:key="id">
  <template is="productItem" data="{{...item}}"/>
</view>

import vs include

import
导入目标文件定义的 template,不会导入目标文件中 import 的其他模板(无传递性)。使用 <template is="name"/> 引用
include
将目标文件中除 template 和 wxs 以外的所有内容直接复制到当前位置,类似于文件内联。常用于复用公共头部/底部
<!-- include 示例 -->
<include src="../../templates/header.wxml"/>
<view class="content">...页面内容...</view>
<include src="../../templates/footer.wxml"/>

3.6 WXS 模块(渲染层脚本)

WXS(WeiXin Script)是可以在 WXML 中运行的脚本,能够在渲染层进行数据处理,避免跨线程通信。常用于数据格式化。

<!-- 内联 WXS 模块 -->
<wxs module="filters">
  var formatPrice = function(price) {
    return (parseFloat(price) / 100).toFixed(2)
  }

  var formatDate = function(timestamp) {
    var d = new Date(timestamp)
    return d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate()
  }

  module.exports = {
    formatPrice: formatPrice,
    formatDate: formatDate
  }
</wxs>

<!-- 使用 WXS 函数格式化数据 -->
<view>¥{{filters.formatPrice(item.priceInCents)}}</view>
<view>{{filters.formatDate(item.createdAt)}}</view>
ℹ️
WXS 的局限性

WXS 使用的是类 ES5 语法(不支持 ES6+),不能调用小程序的 API(如 wx.request),也不能引用 JS 模块。它的运行环境与逻辑层 JS 是隔离的,仅适合做轻量的数据格式化和渲染层交互优化。