当前位置: 首页 > 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.jsqmd.com/news/849550/

相关文章:

  • 【AI语音实战】从VAD到声纹:构建智能对话系统的核心技术栈
  • Grounding DINO实战评测:对比GLIP、OV-DETR,在COCO和LVIS数据集上到底强在哪?
  • 告别文献混乱!用Zotero+OneDrive打造你的跨设备论文库(附ZotFile插件配置)
  • LangChain-Chatchat 开发与应用(六) Agent能力揭秘-让大模型不仅能聊天还能干活
  • 别再手动点点点了!用Inspect.exe + Python搞定Windows桌面自动化测试
  • 别再死记硬背了!用5个真实业务场景拆解SAP EWM的‘上架策略’与‘仓位确定逻辑’
  • PFC2D5.0_从零构建边坡开挖与稳定性分析模型
  • 雀巢冰淇淋在华投资的首家冰淇淋工厂迎来成立40周年 | 美通社头条
  • 告别FTP!用Go写的Filebrowser,一个命令搞定Windows/Linux跨平台文件管理
  • Cinemachine - Unity相机进阶:从基础到实战的镜头艺术
  • 数据科学工具链实战指南:从核心工具到架构选型
  • 2026年耐磨性好的品牌注塑机配件订制/注塑机配件订制/耐高温注塑机配件订制优质供应商推荐 - 品牌宣传支持者
  • 女神异闻录5:皇家版2026最新官方破解版加修改器免费下载 一键转存 永久更新 (看到速转存 资源随时走丢)
  • 从DOCK 6.11新特性到实战:RDKit集成与描述符驱动的药物设计
  • Oracle数据清洗实战:TRIM函数与LTRIM/RTRIM的深度对比与应用
  • 中兴B862AV3.2M盒子救砖记:免拆机、免ADB,一根双公头USB线搞定刷机
  • 别再傻傻分不清了!用大白话讲明白BLE开发里的GATT和GAP到底啥关系
  • 惠州三岛新材料一站式密封胶解决方案!耐高温密封胶、导热硅胶、玻璃胶、导热垫片、环氧AB胶、平面密封胶生产厂家甄选 - 栗子测评
  • 麦当劳中国启动2026全国招聘周招募新生代人才
  • 使用curl命令直接测试taotoken聊天补全接口的详细指南
  • Honeywell 51304650-100终端组件
  • 避坑指南:用ESP32读取NTC温度时,你的ADC精度为什么总是不准?
  • Unity3d 2020 WebGL部署IIS实战:从SyntaxError到wasm加载失败的完整排错指南
  • 批量采购必看:导热硅脂厂家推荐,502胶水/耐高温胶水快干胶/UV胶厂家推荐,源头厂家惠州市三岛新材料可定制可拿样 - 栗子测评
  • 054实现Trie(前缀树)
  • 双人成行2026最新官方正版免费下载 520情侣必玩 一键转存 永久更新 (看到速转存 资源随时走丢)
  • 从‘测量平面’到‘器件平面’:深入浅出图解VNA去嵌背后的信号流与T参数矩阵
  • Jetson Nano项目实战:用udev规则永久绑定USB雷达/传感器,告别串口号漂移烦恼
  • 博德之门2026最新官方正版免费下载 一键转存 永久更新 (看到速转存 资源随时走丢)
  • Perplexity vs. Claude vs. Perplexity Pro订阅转化率对比分析(内部泄露数据首次公开)