当前位置: 首页 > news >正文

第三章 WXML 表单组件全览与实战

第三章 WXML 表单组件全览与实战

📚 系列教程:微信小程序投票系统完整开发
🔗 上一章:第二章 - 小程序目录结构与核心文件详解
🔗 下一章:第四章 - WXSS 样式系统与布局


3.1 WXML 是什么

WXML(WeiXin Markup Language)是小程序的模板语言,类似 HTML,但有以下区别:

对比HTMLWXML
基础容器<div><view>
文字<span><text>
图片<img><image>
链接<a><navigator>
数据绑定无原生支持{{变量名}}
列表渲染无原生支持wx:for
条件渲染无原生支持wx:if

3.2 数据绑定语法

<!-- .wxml 文件 --><view>{{title}}</view><view>{{count + 1}}</view><view>{{isShow ? '显示' : '隐藏'}}</view><imagesrc="{{imgUrl}}"/><inputvalue="{{inputVal}}"/>
// .js 文件Page({data:{title:'投票系统',count:10,isShow:true,imgUrl:'/images/logo.png',inputVal:'默认值'}})

3.3 基础容器组件

view — 块级容器(最常用)

<!-- 基础用法 --><viewclass="container">内容</view><!-- hover 点击效果 --><viewhover-class="hover"hover-stay-time="100">点我有变色</view>

text — 文字组件

<!-- 基础文字 --><text>普通文字</text><!-- 可选中文字(用户可长按复制) --><textselectable="true">可选中的文字</text><!-- 解析转义字符 --><textdecode="true">5&gt;3</text><!-- 多行文字与换行 --><text>第一行\n第二行</text>

📌<text>内部不能嵌套<view>,只能放文字和<text>

image — 图片组件

<!-- 基础图片 --><imagesrc="/images/logo.png"mode="aspectFit"/><!-- 网络图片 --><imagesrc="https://example.com/img.jpg"mode="aspectFill"/><!-- 懒加载(进入视口才加载) --><imagesrc="{{item.imgUrl}}"lazy-load="true"/>

mode 属性(重要)

mode说明
scaleToFill拉伸填满,可能变形(默认)
aspectFit保持比例,完整显示,可能留白
aspectFill保持比例,填满容器,可能裁剪 ⭐
widthFix宽度固定,高度自适应

scroll-view — 可滚动视图

<!-- 纵向滚动 --><scroll-viewscroll-y="true"style="height:500rpx;"bindscrolltolower="onLoadMore"><viewwx:for="{{list}}"wx:key="id">{{item.name}}</view></scroll-view><!-- 横向滚动 --><scroll-viewscroll-x="true"style="white-space:nowrap;"><viewstyle="display:inline-block;"wx:for="{{tabs}}"wx:key="id">{{item}}</view></scroll-view>

3.4 表单组件详解

input — 输入框

<inputtype="text"value="{{form.title}}"placeholder="请输入投票标题"placeholder-class="placeholder-style"placeholder-style="color: #ccc; font-size: 28rpx;"maxlength="50"disabled="{{false}}"focus="{{autoFocus}}"confirm-type="done"bindinput="onTitleInput"bindfocus="onFocus"bindblur="onBlur"bindconfirm="onConfirm"/>

type 属性值

type说明键盘样式
text普通文本(默认)普通键盘
number数字数字键盘
digit带小数的数字数字+小数点键盘
idcard身份证数字+X键盘
nickname昵称(会弹出填写昵称弹窗)特殊处理

事件说明

onTitleInput(e){// e.detail.value = 当前输入框的完整值(不是变化量!)this.setData({'form.title':e.detail.value})},onFocus(e){// e.detail.height = 键盘高度(可用于调整布局)},onBlur(e){// 失去焦点时触发},onConfirm(e){// 点击键盘右下角确认键时触发// e.detail.value = 当前值}

textarea — 多行输入框

<textareavalue="{{content}}"placeholder="请输入详细描述(选填)"maxlength="200"auto-height="true"show-confirm-bar="false"bindinput="onContentInput"style="width:100%;"/>

⚠️注意:textarea 在 iOS 上有覆盖层问题,如果页面有 fixed 定位的元素(比如底部按钮),需要特殊处理。

button — 按钮

<!-- 三种类型 --><buttontype="primary">绿色主按钮</button><buttontype="default">白色默认按钮</button><buttontype="warn">红色警告按钮</button><!-- 小尺寸 --><buttonsize="mini"type="primary">小按钮</button><!-- 镂空样式 --><buttonplain="true"type="primary">镂空按钮</button><!-- loading 状态 --><buttonloading="{{isSubmitting}}"disabled="{{isSubmitting}}"type="primary">{{isSubmitting ? '提交中...' : '立即提交'}}</button><!-- 开放能力 --><buttonopen-type="share">分享给朋友</button><buttonopen-type="getUserInfo"bindgetuserinfo="onGetUserInfo">获取头像昵称</button><buttonopen-type="getPhoneNumber"bindgetphonenumber="onGetPhone">获取手机号(需企业认证)</button>

radio — 单选框(投票单选必用)

<!-- 方式一:radio-group 包裹(推荐) --><radio-groupbindchange="onTypeChange"><labelclass="radio-item"><radiovalue="1"checked="{{form.type === '1'}}"/><text>单选投票</text></label><labelclass="radio-item"><radiovalue="2"checked="{{form.type === '2'}}"/><text>多选投票</text></label></radio-group>
onTypeChange(e){// e.detail.value = 被选中 radio 的 value 值this.setData({'form.type':e.detail.value})}

checkbox — 复选框(投票多选必用)

<checkbox-groupbindchange="onOptionsChange"><viewwx:for="{{options}}"wx:key="id"class="option-item"><checkboxvalue="{{item.id}}"checked="{{item.checked}}"/><text>{{item.content}}</text></view></checkbox-group>
onOptionsChange(e){// e.detail.value = 所有选中项的 value 组成的数组// 例:['1', '3', '5']this.setData({selectedOptionIds:e.detail.value})}

⚠️注意:微信原生 checkbox 的样式很丑,投票系统中我们用自定义样式来实现更好看的效果(第九章详解)。

switch — 开关

<switchchecked="{{isMultiple}}"bindchange="onSwitchChange"color="#07C160"type="switch"/>
onSwitchChange(e){// e.detail.value = true/falsethis.setData({isMultiple:e.detail.value})}

picker — 选择器

<!-- 普通选择器 --><pickermode="selector"range="{{typeArray}}"range-key="label"value="{{typeIndex}}"bindchange="onPickerChange"><viewclass="picker-display">当前选择:{{typeArray[typeIndex].label}}</view></picker><!-- 日期选择器 --><pickermode="date"value="{{endDate}}"start="2024-01-01"bindchange="onDateChange"><view>截止日期:{{endDate}}</view></picker><!-- 多列选择器 --><pickermode="multiSelector"value="{{multiVal}}"range="{{multiArray}}"bindchange="onMultiChange"><view>{{multiVal}}</view></picker>

slider — 滑块

<slidermin="1"max="10"step="1"value="{{maxChoices}}"show-value="true"active-color="#07C160"bindchange="onSliderChange"bindchanging="onSliderChanging"/>

form — 表单整体提交

<formbindsubmit="onFormSubmit"bindreset="onFormReset"><inputname="title"value="{{form.title}}"placeholder="投票标题"/><radio-groupname="type"><radiovalue="1"checked/>单选<radiovalue="2"/>多选</radio-group><buttonform-type="submit">提交</button><buttonform-type="reset">重置</button></form>
onFormSubmit(e){// e.detail.value = { title: '...', type: '1' }// 所有有 name 属性的表单元素的值会被收集到这里console.log(e.detail.value)}

3.5 列表渲染 wx:for

<!-- 基础用法 --><viewwx:for="{{options}}"wx:key="id">{{item.content}}</view><!-- 自定义变量名(防止嵌套时冲突)--><viewwx:for="{{voteList}}"wx:key="id"wx:for-item="vote"wx:for-index="idx"><viewwx:for="{{vote.options}}"wx:key="id"wx:for-item="opt">{{idx}}. {{vote.title}} - {{opt.content}}</view></view>

wx:key 的值

wx:key="id" ← 使用数组元素的某个属性(推荐,必须唯一) wx:key="*this" ← 使用数组元素本身(适合字符串数组) wx:key="index" ← 用下标(不推荐,会有性能警告)

3.6 条件渲染 wx:if

<!-- wx:if:条件为 false 时销毁 DOM(适合切换不频繁的场景) --><viewwx:if="{{type === 'single'}}">单选模式</view><viewwx:elif="{{type === 'multi'}}">多选模式</view><viewwx:else>未设置</view><!-- hidden:条件为 true 时隐藏(display:none,DOM 保留,适合频繁切换)--><viewhidden="{{!isExpanded}}">展开的内容</view>

📌选择依据

  • 初次渲染较重、切换不频繁 → 用wx:if
  • 需要频繁切换(如 Tab 内容)→ 用hidden

3.7 模板 template

将重复使用的 WXML 片段抽取为模板:

<!-- 定义模板 --><templatename="voteCard"><viewclass="vote-card"><textclass="title">{{title}}</text><textclass="count">{{count}}人参与</text></view></template><!-- 使用模板 --><templateis="voteCard"data="{{title: item.title, count: item.totalVotes}}"/>

3.8 事件系统详解

事件绑定方式

<!-- bind:冒泡事件(会向父元素传播) --><viewbindtap="onTap">点击冒泡</view><!-- catch:阻止冒泡 --><viewcatchtap="onTap">点击不冒泡</view><!-- mut-bind:互斥事件(同层中只有一个能触发) --><viewmut-bind:tap="onTap">互斥点击</view>

传递参数><viewbindtap="onVoteItemClick"data-id="{{item.id}}"data-title="{{item.title}}"data-index="{{index}}">{{item.title}}</view>
onVoteItemClick(e){// dataset 中的键名会自动转换为小驼峰const{id,title,index}=e.currentTarget.dataset// e.currentTarget.dataset ← 绑定事件的元素的 dataset// e.target.dataset ← 触发事件的元素的 dataset(可能是子元素)}

常用事件类型

事件触发时机
tap手指触摸后抬起(类似 click)
longpress长按 300ms+
touchstart手指触摸开始
touchmove手指移动
touchend手指触摸结束
input输入框内容变化
focus获得焦点
blur失去焦点
changeradio/checkbox/picker 等值变化
submit表单提交
scroll滚动时

本章小结

✅ 掌握了 WXML 与 HTML 的核心区别
✅ 学会了所有表单组件的使用(input/textarea/button/radio/checkbox/picker 等)
✅ 掌握了wx:for列表渲染和wx:key的正确使用
✅ 理解了wx:ifhidden的使用场景区别
✅ 学会了通过data-xxx在事件中传递参数

下一章:学习 WXSS 样式系统,包括 rpx 单位、Flex 布局,让投票界面变得好看。


章节:3 / 15 | 更新时间:2026-05-18

http://www.zskr.cn/news/1326156.html

相关文章:

  • 手把手教你搞定KEIL4.74社区版激活:从注册到填问卷拿License的全流程避坑
  • 39. UE5 GAS RPG:利用Motion Warping实现技能释放时的智能角色转向
  • LangChain-Chatchat 开发与应用(六) Agent能力揭秘-让大模型不仅能聊天还能干活
  • VCSA底层网络配置实战:从IP修改到SSH登录的运维指南
  • Cinemachine - Unity相机进阶:从基础到实战的镜头艺术
  • 基于安信可VC-02与Wi-Fi 6模组打造毫秒级本地智能家居语音控制方案
  • 从DOCK 6.11新特性到实战:RDKit集成与描述符驱动的药物设计
  • STM32F103 ADC多通道采样,用DMA搬运数据到底有多省心?一个数组搞定所有
  • 惠州三岛新材料一站式密封胶解决方案!耐高温密封胶、导热硅胶、玻璃胶、导热垫片、环氧AB胶、平面密封胶生产厂家甄选 - 栗子测评
  • 中小团队如何利用Taotoken用量看板实现API成本精细化管理
  • 为开源Agent工具OpenClaw配置Taotoken作为后端模型的详细教程
  • Unity3d 2020 WebGL部署IIS实战:从SyntaxError到wasm加载失败的完整排错指南
  • 别再死记硬背了!用一张图+三个故事彻底搞懂PCIe TLP帧结构
  • Jetson Nano项目实战:用udev规则永久绑定USB雷达/传感器,告别串口号漂移烦恼
  • 数据分析篇---U型关系与与阈值效应
  • HarmonyOS实战解析:ServiceExtensionAbility的启动、连接与生命周期管理
  • 2026年质量好的长春钢模板/长春钢模板出租/钢模板买卖/钢模板出租品牌厂家推荐 - 品牌宣传支持者
  • CVUSA:跨视角地理定位的基石数据集详解(含论文与资源)
  • Perplexity旅游信息可信度危机:权威信源交叉验证协议(ISO/IEC 25010合规版)首次公开
  • University-1652:首个基于无人机的跨视角地理定位数据集
  • 09. 极速:多级缓存策略与 LRU 算法实战
  • 双人成行2026最新官方正版免费下载 520情侣必玩 一键转存 永久更新 (看到速转存 资源随时走丢)
  • 别再折腾解码器了!用DXVA Checker和GPU-Z一键排查Chrome播不了H265视频的根源
  • 为什么Google Sans Code是程序员的终极选择?5大核心优势详解
  • STM32F407标准库USB Host驱动广和通MC665模块:从官方例程到实战移植的保姆级避坑指南
  • 一文读懂机箱机柜供应商:惠州市凌泰实业,深耕工控/钣金/铝型材/轨道交通/车载信号/仪器仪表/便携式机箱定制配件专业生产 - 栗子测评
  • 避坑指南:RK3568多屏配置中那些让你uboot启动失败的GPIO和PWM复用陷阱
  • 不用Remix在线版!在VSCode里用Hardhat写合约,搭配Ganache和MetaMask本地测试全流程
  • 告别文献混乱!用Zotero+OneDrive打造你的跨设备论文库(附ZotFile插件配置)
  • 2026年评价高的烟台装修公司/烟台全包装修公司/烟台毛坯房装修公司/烟台二手房翻新装修公司哪家经验丰富 - 行业平台推荐