ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

form 用法

form 用法 一、form 是做什么的form 是表单容器。它本身不负责输入而是把放在它内部的若干表单组件input、switch、checkbox、slider、radio、picker的值集中收集起来在用户点击提交按钮时一次性交给页面逻辑。没有 form就得给每个输入框单独绑定 bindinput、各自维护一个 data 字段有了 form只需要给每个控件起个 name提交时就能一次性拿到全部值。1.1 form 的三条基本规则这三条是这个组件全部用法的核心记住就能用规则具体做法① 用 name 当字段名每个需要提交的控件都要写 name提交时 name 就是结果的 key② 用 form-type 的按钮触发form 内部的 button 设置 form-typesubmit 才会提交设为 reset 则重置表单③ 在 bindsubmit 里取值通过事件对象的 e.detail.value 拿到 { name: value } 形式的数据1.2 form 的属性属性类型默认值说明report-submitbooleanfalse是否返回 formId 用于发送模板消息report-submit-timeoutnumber0等待一段时间毫秒以确认 formId 是否生效bind:submiteventhandle—携带 form 中的数据触发e.detail { value, formId }bind:reseteventhandle—表单重置时触发bind:submitToGroupeventhandle—发送文本到聊天后触发需配合 textarea表中属性与默认值取自微信官方 form 组件文档。1.3 需要认识的三个配套组件组件在本项目中的角色input输入框用 name 提供 a / b / c 三个字段button按钮用 form-type 决定是提交还是重置view承载标题与结果显示不参与表单提交二、本项目做了什么miniprogram-8 是一个三角形面积计算器用户输入三条边长点击计算页面用海伦公式算出面积并显示如果三条边构不成三角形则弹出提示。这个小项目的价值在于它把 form 的完整链路都走了一遍——输入、收集、提交、校验、反馈、重置而且代码量很小适合逐行读。miniprogram-8 ├── app.js ├── app.json ├── app.wxss ├── components │ └── navigation-bar │ ├── navigation-bar.js │ ├── navigation-bar.json │ ├── navigation-bar.wxml │ └── navigation-bar.wxss ├── pages │ └── index │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── project.config.json ├── project.private.config.json └── sitemap.json2.1 页面结构index.wxml!--index.wxml-- navigation-bar titleWeixin back{{false}} colorblack background#FFF/navigation-bar scroll-view classscrollarea scroll-y typelist view classbox view classtitle三角形面积计算器/view form bindsubmitformSubmit input typedigit placeholder请输入三角形第一条边长 namea focustrue value{{sideA}}/ input typedigit placeholder请输入三角形第二条边长 nameb value{{sideB}}/ input typedigit placeholder请输入三角形第三条边长 namec value{{sideC}}/ button typeprimary form-typesubmit计算/button button typewarn form-typereset重置/button /form view wx:if{{visible}} classresult三角形的面积为{{area}}/view /view /scroll-view2.2 页面逻辑index.js// index.js Page({ data:{ visible:false, }, formSubmit(e){ console.log(e); let visible this.data.visible let sideANum parseFloat(e.detail.value.a) let sideBNum parseFloat(e.detail.value.b) let sideCNum parseFloat(e.detail.value.c) let area 0 console.log(sideANum,sideBNum,sideCNum); if((sideANumsideBNumsideCNum)||(sideANumsideCNumsideBNum)||(sideBNumsideCNumsideANum)){ this.clear() wx.showToast({ title:问题三角形的两条边之和小于等于第三条边, icon:none, duration:2000 }) return }else{ const s (sideANumsideBNumsideCNum)/2 area Math.sqrt(s*(s-sideANum)*(s-sideBNum)*(s-sideCNum)) } if(area0){ visible true }else{ visible false } this.setData({ area, visible }) }, clear(){ this.setData({ sideA:, sideB:, sideC:, visible: false }) } })2.3 样式index.wxsspage{ height: 100vh; display: flex; flex-direction: column; } .scrollarea{ flex: 1; overflow-y: hidden; } input, button{ font-size: 40rpx; margin: 40rpx 0; } input{ border-bottom: 2rpx solid blue; } .result{ font-size: 40rpx; color: blue; }三、form 用法四步走把上面的代码拆开看使用 form 只有四步。3.1 第一步用 form 包住所有输入控件form bindsubmitformSubmit...所有需要提交的控件.../formform 是一个容器只有写在它内部的控件才会被收集。写在 form 外面的 input提交时不会出现在 e.detail.value 里。3.2 第二步给每个控件加 nameinput typedigit placeholder请输入三角形第一条边长 namea /input typedigit placeholder请输入三角形第二条边长 nameb /input typedigit placeholder请输入三角形第三条边长 namec /name 就是提交结果里的 key。本项目用了 a、b、c 三个短名字因此提交后拿到的是 { a: ..., b: ..., c: ... }。提示name 要起得有含义。如果字段多用 sideA、sideB、sideC 这样的名字会比 a、b、c 更好维护。3.3 第三步放一个 form-typesubmit 的按钮button typeprimary form-typesubmit计算/buttonbutton typewarn form-typereset重置/buttonbutton 的 form-type 有两个取值submit 表示点击后提交表单触发 form 的 bindsubmitreset 表示点击后重置表单触发 form 的 bindreset。type 属性则只管外观primary 是绿色主按钮warn 是红色警示按钮默认是灰色。3.4 第四步在 bindsubmit 的处理函数里取值formSubmit(e){let sideANum parseFloat(e.detail.value.a)let sideBNum parseFloat(e.detail.value.b)let sideCNum parseFloat(e.detail.value.c)}注意两点一是数据在 e.detail.value 里不是 e.detail二是拿到的永远是字符串即使用了 typedigit 的数字键盘取出来的也是字符串所以本项目用 parseFloat 转成数字再计算。3.5 事件对象长什么样属性内容e.detail.value字段名到值的映射形如 { a: 3, b: 4, c: 5 }e.detail.formId仅当 form 设置了 report-submit 时才有值e.type事件类型这里是 submit四、input 与 button 的关键属性4.1 input 在本项目用到的属性属性本项目取值说明namea / b / cform 提交时的字段名必需typedigit带小数点的数字键盘纯整数可用 numberplaceholder请输入三角形第 N 条边长输入框为空时的提示文字value{{sideA}} 等输入框的初始内容由数据绑定控制focustrue仅第一个是否获取焦点本项目让第一个输入框自动聚焦input 的 type 合法值text文本键盘、number数字键盘、idcard身份证、digit带小数点的数字键盘、safe-password、nickname。本项目的边长可能带小数所以选 digit。4.2 button 的 form-typeform-type 取值点击后发生什么本项目对应submit触发表单的 bindsubmit 事件携带所有 name 的值计算按钮reset触发原生表单重置清空表单控件的值重置按钮4.3 重置的两种做法重要区别这是本项目最值得注意的一个设计点。重置表单其实有两种做法效果并不一样做法写法会不会清空页面上的计算结果原生重置button form-typereset不会。它只重置表单控件不改变 data自己写重置button bindtapclear会。因为 clear() 里 setData 了 visible: false原生重置 监听form bindresetclear会。既能原生重置输入又能顺带清理 data本项目用的是原生重置而 clear() 只在「三条边构不成三角形」的错误分支里被调用。这带来一个实际问题写在第六节。五、计算逻辑海伦公式项目用海伦公式Herons formula求三角形面积已知三边 a、b、c先求半周长 s (a b c) / 2则面积 √(s(s-a)(s-b)(s-c))。const s (sideANumsideBNumsideCNum)/2area Math.sqrt(s*(s-sideANum)*(s-sideBNum)*(s-sideCNum))因为要开平方所以必须先判断三边能否构成三角形。判据是任意两边之和大于第三边因此代码里对三种组合都做了检查if((sideANumsideBNumsideCNum)||(sideANumsideCNumsideBNum)||(sideBNumsideCNumsideANum)){this.clear()wx.showToast({title:问题三角形的两条边之和小于等于第三条边,icon:none,duration:2000})return}这里有三个细节处理得不错一是用 而不是 判断能同时排除「退化成一条直线」的情况二是校验失败时先 clear() 再 return避免上一次的结果残留三是用 wx.showToast 配合 icon 设为 none 给出可读的提示而不是静默失败。六、通读代码后发现的问题6.1 点击「重置」不会清空已显示的结果建议修现象先输入一组能构成三角形的边长并点击计算结果正常显示此时点击「重置」三个输入框会被清空但页面上那行面积结果依然留在那里。原因重置按钮用的是 form-typereset它触发的是原生表单重置只清空输入控件不会改变 data 里的 visible而唯一能把 visible 置回 false 的 clear() 方法只在三角形校验失败的分支里被调用过重置按钮并没有绑定它。最小改法是给 form 补上 bindreset让原生重置顺便把 data 也清干净form bindsubmitformSubmit bindresetclear这样点「重置」时既会原生清空输入框也会执行 clear() 把 visible 置为 false结果那一行就随之消失了。6.2 输入非数字时会静默失败建议修如果用户没有输入、或者输入了非数字内容parseFloat 会得到 NaN。此时三角形的三个判据都是 NaN 比较结果全为 false于是代码认为通过了校验继续用 NaN 去算面积得到 area NaN接下来判断 area 0 为 falsevisible 被置为 false于是页面既不显示结果也不弹任何提示。建议在取值之后先做一次有效性判断例如if(isNaN(sideANum) || isNaN(sideBNum) || isNaN(sideCNum)){this.clear()wx.showToast({ title:请先输入三条边长, icon:none, duration:2000 })return}6.3 data 里没有声明三个输入框绑定的字段index.wxml 里三个输入框分别绑定了 {{sideA}}、{{sideB}}、{{sideC}}clear() 里也 setData 了这三个字段但 data 初始只声明了 visible: false。小程序允许 setData 添加原本不存在的字段所以功能能跑通。但把模板用到的字段都先在 data 里声明出来可读性更好也便于排查问题data:{visible:false,sideA:,sideB:,sideC:}6.4 其他小问题位置现状建议formSubmit保留了两处 console.log(e)调试完可删除或改为有针对性的一条日志formSubmit 上方JSDoc 注释块是空的只有 param {*} e补上说明或直接删掉空注释navigation-bartitleWeixin改成页面实际标题如「三角形面积计算器」formSubmitlet visible this.data.visible 之后又整体重算直接算好再一次性 setData减少中间变量
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进