网站已运行 162 · 21小时 · 33 · 01
目录

微信小程序 wx:for 列表渲染:wx:key 与 block 实测

数组通过循环展开成三个 WXML 列表节点并由唯一 key 对应的示意图

微信小程序 wx:for 用来把页面 data 中的数组展开成一组 WXML 节点。语法本身不难,真正容易出错的是三个细节:循环数据写在哪、什么时候需要 <block>,以及 wx:key 应该填字段名还是 *this

这篇不另造一个只为截图存在的示例。我直接使用此前在微信开发者工具和 iPhone 真机中运行过的原生分包项目,抽取首页的“当前代码包”列表,并用脚本重新核对 WXML、页面 data 和最终三项输出之间是否一致。

先看这次真实项目里的列表

首页需要显示主包、普通分包和独立分包三个标签。数据放在 pages/home/index.jsdata 中:

Page({
  data: {
    packageSummary: [
      '主包:home、profile',
      '普通分包:packages/order',
      '独立分包:packages/campaign'
    ]
  }
})

WXML 不需要手写三个重复的 view。循环写在一个虚拟 block 上,数组中的每个字符串通过 {{item}} 输出:

<block wx:for="{{packageSummary}}" wx:key="*this">
  <view class="tag">{{item}}</view>
</block>

本轮静态检查实际读取了这两个文件,并捕获页面定义中的数组。六项断言全部通过:数据确实是数组、循环指向 packageSummary、使用虚拟 block、存在 item 绑定、字符串列表使用 *this,而且三项 key 均不重复。

indexitem / key渲染结果
0主包:home、profile一个标签节点
1普通分包:packages/order一个标签节点
2独立分包:packages/campaign一个标签节点

也就是说,一份三项数组最终生成三个同结构节点;WXML 负责描述重复结构,具体内容仍以页面 data 为事实来源。

wx:for 默认提供 item 和 index

wx:for 展开数组时,会在循环内部提供两个临时变量:

  • item:当前这一项的值。
  • index:当前项在数组中的下标,从 0 开始。
<view wx:for="{{packageSummary}}" wx:key="*this">
  第 {{index}} 项:{{item}}
</view>

如果内层结构也有循环,继续使用默认名字很容易把外层 item 遮住。可以显式改名:

<view
  wx:for="{{packageSummary}}"
  wx:for-item="packageItem"
  wx:for-index="packageIndex"
  wx:key="*this"
>
  {{packageIndex}}:{{packageItem}}
</view>

改名不会改变原数组,只是让当前模板里的临时变量更明确。嵌套列表、表格行或卡片内再循环标签时,这个习惯比到处猜 item 属于哪一层更可靠。

什么时候把 wx:for 写在 block 上

如果每次循环只生成一个根节点,把 wx:for 直接写在这个节点上即可。只有一次循环要生成多个同级节点时,才需要用 <block> 包起来:

<block wx:for="{{orders}}" wx:key="id">
  <view class="order-title">{{item.title}}</view>
  <view class="order-price">{{item.price}}</view>
</block>

block 是 WXML 的虚拟包装,不会像普通 view 那样额外生成一个可见容器。它适合组织模板逻辑,但不能把它当成真实布局元素去设置 class、间距或背景;需要参与布局时,仍应使用 view

wx:key:字段名和 *this 怎么选

wx:key 用于在列表变化时标识每一项。最常见的两种写法对应两类数据。

对象数组:直接写稳定字段名

Page({
  data: {
    orders: [
      { id: 'A1001', title: '订单一' },
      { id: 'A1002', title: '订单二' }
    ]
  }
})
<view wx:for="{{orders}}" wx:key="id">
  {{item.title}}
</view>

这里写的是 wx:key="id",不是 wx:key="{{item.id}}"。key 值来自当前对象的 id 字段;这个字段应尽量唯一,而且不要因为排序或文案变化而改变。

字符串或数字数组:可使用 *this

本次项目中的 packageSummary 是字符串数组,没有 id 字段,因此使用 wx:key="*this",让当前字符串本身作为 key。前提是各项不重复;如果数组里出现两个完全相同的字符串,它们就不能提供足够稳定的区分。

不要把“所有列表都必须加 key”当成定律

微信当前官方文档特别说明:使用 wx:key 不一定提升列表渲染性能,有时反而可能带来负面影响。固定不变的列表、只在末尾增加或删除项目的列表,或者找不到有代表性字段的列表,不应为了消除心理负担而随便拿 index、标题或会变化的值充当 key。

更实用的判断是:列表是否会重排或在中间插入、删除?每项是否有稳定且唯一的业务标识?两项都成立时再选 key,通常比机械复制旧教程更稳妥。

四个常见错误怎么查

现象优先检查处理方式
页面一个节点都没有wx:for 指向的字段名确认字段确实位于当前页面或组件的 data,并且值是数组
文字显示为空循环变量名称确认使用默认 item,或与 wx:for-item 的自定义名称一致
出现 key 警告或更新错位key 是否重复、是否会变化对象使用稳定唯一字段;原始值数组只有在值唯一时使用 *this
样式包不住多节点是否把 block 当成真实容器需要布局和样式时改用 view,不要给虚拟 block 承担布局

如果文件路径、页面注册或全局配置本身有问题,先对照微信小程序项目目录结构app.json 与页面 JSON 的作用域排除基础问题。列表恰好位于分包页面时,再检查subPackages 的 root 与页面路径,不要把“页面没注册”误判成 wx:for 失效。

列表项同时包含整行点击和行内按钮时,还要留意 tap 事件继续向父级传播;可结合微信小程序 bindtap 与 catchtap 的事件冒泡实作一起排查重复触发。

如何复现本次检查

项目根目录下执行本次检查脚本:

node codex-wechat-mini-program/verify-wxml-list-rendering.mjs

脚本会读取真实的 pages/home/index.wxmlpages/home/index.js,捕获页面 data,检查循环目标、虚拟 block、*thisitem 绑定和 key 唯一性。本轮结果为 6 项全部通过,输出三条与数组顺序一致的标签数据。

官方资料:微信开放文档《数据绑定》微信开放文档《列表渲染》(访问日期:2026-08-29;本次项目此前实测工具为微信开发者工具 Stable 2.02.2608060、基础库 3.17.1,本轮结论重新以当前官方 WXML 文档和项目静态断言核对)。

数臻源码猫咪图标
目录
数臻源码猫咪图标

目录

标签云: