news 2026/10/4 11:04:24

HarmonyOS 应用 · 寝室投票创建页深度解析:选项动态增删与不可变更新

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS 应用 · 寝室投票创建页深度解析:选项动态增删与不可变更新

HarmonyOS 应用 · 寝室投票创建页深度解析:选项动态增删与不可变更新

项目编号:49-dorm-vote 技术栈:HarmonyOS ArkTS · ArkUI 声明式 UI · Stage 模型 本篇页面:创建页Func1Tab.ets(114 行) 系列导航:(一)首页 ·(二)创建· (三)投票 · (四)结果


一、三个操作方法:增删改的三重边界

@State question: string = ''; @State options: string[] = ['', '']; @State multiChoice: boolean = false; private addOption(): void { if (this.options.length < 6) { this.options.push(''); this.options = this.options.slice(); } } private removeOption(idx: number): void { if (this.options.length > 2) { this.options.splice(idx, 1); this.options = this.options.slice(); } } private setOption(idx: number, v: string): void { this.options[idx] = v; }

三个@State:question(问题)、options(选项数组,初始 2 个空串)、multiChoice(多选开关)。三个方法构成增删改三重边界:

  • addOption():length < 6上限 6 个选项,push('')追加空选项 +slice()生成新引用触发刷新
  • removeOption(idx):length > 2下限 2 个选项,splice(idx, 1)删除 +slice()触发刷新
  • setOption(idx, v):直接赋值options[idx] = v——修改无需新引用(ForEach 的 key 是索引,输入不影响列表结构)

投票至少 2 个选项、最多 6 个——边界的存在保证投票的合法性(1 个选项无意义,太多选项难以决策)。


二、页面骨架:QuestionCard + OptionCard + SettingCard + Button

build() { Column() { this.Header() Scroll() { Column({ space: 16 }) { this.QuestionCard() this.OptionCard() this.SettingCard() Button('发起投票').fontSize(15).fontColor('#FFFFFF').backgroundColor(C.primary) .width('100%').height(48).borderRadius(D.rMd) .onClick(() => { promptAction.showToast({ message: this.question.length > 0 ? '投票已发起' : '请填写投票问题' }); }) } .width('100%') .padding({ left: D.pad, right: D.pad, top: 16, bottom: D.pad + this.safeBottom + 20 }) } .layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top) } .width('100%').height('100%').backgroundColor(C.bg) }

Header 在 Scroll 外固定,Scroll 内四块:QuestionCard(问题)+ OptionCard(选项)+ SettingCard(多选设置)+ Button(发起投票)。按钮onClick空值校验:question.length > 0才提示"投票已发起"。


三、QuestionCard:问题输入

@Builder QuestionCard() { Column({ space: 10 }) { Text('投票问题').fontSize(14).fontWeight(FontWeight.Bold).fontColor(C.text).width('100%') TextInput({ placeholder: '例如:今晚点什么外卖?' }) .backgroundColor(C.cardSoft).borderRadius(D.rSm).height(44) .onChange((v: string) => { this.question = v; }) } .width('100%').padding(16).backgroundColor(C.card).borderRadius(D.rLg).border({ width: 1, color: C.stroke }) }

14 号加粗"投票问题" +TextInput,placeholder带示例"例如:今晚点什么外卖?"——示例占位符降低用户输入门槛。onChange写入this.question。


四、OptionCard:动态选项列表

@Builder OptionCard() { Column({ space: 12 }) { Text('候选选项').fontSize(14).fontWeight(FontWeight.Bold).fontColor(C.text).width('100%') ForEach(this.options, (opt: string, idx: number) => { Row({ space: 10 }) { Text((idx + 1).toString()).fontSize(13).fontColor(C.primary) .width(26).height(26).textAlign(TextAlign.Center).backgroundColor(C.primarySoft).borderRadius(13) TextInput({ placeholder: '选项 ' + (idx + 1), text: this.options[idx] }) .backgroundColor(C.cardSoft).borderRadius(D.rSm).height(42).layoutWeight(1) .onChange((v: string) => { this.setOption(idx, v); }) if (this.options.length > 2) { Text('✕').fontSize(16).fontColor(C.textDim) .onClick(() => { this.removeOption(idx); }) } }.width('100%') }, (opt: string, idx: number) => idx.toString()) if (this.options.length < 6) { Row({ space: 6 }) { Text('+').fontSize(16).fontColor(C.primary) Text('添加选项').fontSize(13).fontColor(C.primary) } .width('100%').justifyContent(FlexAlign.Center).padding({ top: 10, bottom: 10 }) .backgroundColor(C.cardSoft).borderRadius(D.rSm) .onClick(() => { this.addOption(); }) } } .width('100%').padding(16).backgroundColor(C.card).borderRadius(D.rLg).border({ width: 1, color: C.stroke }) }

三个条件渲染——if分支控制增删按钮:

// 序号圆:26×26 浅粉底 + 紫色序号 Text((idx + 1).toString()).width(26).height(26).backgroundColor(C.primarySoft).borderRadius(13) // ✕ 删除按钮:选项数 > 2 时渲染 if (this.options.length > 2) { Text('✕').onClick(() => { this.removeOption(idx); }) } // + 添加按钮:选项数 < 6 时渲染 if (this.options.length < 6) { Row({ space: 6 }) { ... }.onClick(() => { this.addOption(); }) }

恰好 2 个选项时无 ✕(下限保护),恰好 6 个选项时无 + (上限保护)——条件渲染与增删边界严格对应。TextInput的text: this.options[idx]绑定当前值,onChange调setOption(idx, v)写回数组。

ForEach key 用idx.toString()——选项是动态增删的列表,索引用作 key 保证增删时列表正确重建。


五、SettingCard:Toggle 多选开关

@Builder SettingCard() { Row() { Column({ space: 2 }) { Text('允许多选').fontSize(14).fontColor(C.text) Text('开启后可选择多个选项').fontSize(11).fontColor(C.textDim) }.alignItems(HorizontalAlign.Start).layoutWeight(1) Toggle({ type: ToggleType.Switch, isOn: this.multiChoice }) .selectedColor(C.primary) .onChange((v: boolean) => { this.multiChoice = v; }) } .width('100%').padding(16).backgroundColor(C.card).borderRadius(D.rLg).border({ width: 1, color: C.stroke }) }

Toggle({ type: ToggleType.Switch, isOn: this.multiChoice })+selectedColor(C.primary)开启时粉色圆点。onChange写回this.multiChoice。左侧双行文案:14 号"允许多选" + 11 号灰色说明"开启后可选择多个选项"。


六、可演进方向

方向现状改法收益
发起写入Toast 模拟追加到首页 votes 数组投票真实创建
选项校验仅问题校验校验选项非空 + 去重选项合法
截止时间无DatePicker 设置截止投票限时结束
匿名投票无匿名开关 + 结果隐藏投票人隐私保护
表单重置无发起后清空 question/options连续创建

创建页是投票的录入入口——三个操作方法(增删改)+ 三重边界(2 下限/6 上限/条件渲染)。从push + slice的不可变更新到Toggle的多选开关,每一层都有明确的职责边界。

系列导航:(一)首页 ·(二)创建· (三)投票 · (四)结果

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 11:03:45

Anaconda下Qt平台插件初始化失败?四套方案彻底解决PyQt/PySide报错

有一类报错&#xff0c;几乎每个在 Anaconda 里跑过带界面程序的人都会撞见&#xff1a;no qt platform plugin could be initialized。我第一次碰到&#xff0c;是在 Anaconda 环境里用 PyQt5 写一个小工具&#xff0c;程序一启动就崩&#xff0c;控制台只有这半句话&#xff…

作者头像 李华
网站建设 2026/10/4 10:59:35

GitHub项目推荐--Kimi CLI:下一代命令行AI助手接入TaoToken实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/4 10:58:06

MRAM在工业嵌入式系统中的选型与实战设计

1. 为什么选 MR25H40CDF 而不是 Flash 或 EEPROM&#xff1f;——工业级数据存储的底层逻辑在工业现场和嵌入式设备里&#xff0c;数据存储从来不是“能存就行”的问题。我做过三个不同产线的数据记录模块&#xff1a;一个是温湿度传感器节点&#xff0c;要求断电后毫秒级保存最…

作者头像 李华
网站建设 2026/10/4 10:57:59

MRAM在工业控制器中的应用:PIC18驱动MR25H40CDF的存储设计

去年给一台工业控制器做改版&#xff0c;最头疼的不是控制逻辑&#xff0c;而是数据存储。原来的方案用串行EEPROM&#xff0c;每10秒写一条40字节的运行日志&#xff0c;两个月后回读发现参数被改得乱七八糟。查寿命手册才发现&#xff0c;照这个写入频率&#xff0c;擦写次数…

作者头像 李华