前言参考官方文档https://docs.rs/xilem/latest/xilem/view/fn.text_input.html版本Xilem 0.4一、text_input基础概念text_input 是可编辑文本输入框组件接收用户键盘输入字符串。区分三个文本组件label 只读展示文本不可选中复制prose 只读展示文本支持鼠标选中复制不可编辑text_input 可编辑输入框允许用户键盘修改内容核心规则输入框内容必须保存在App状态中。输入发生变化通过 on_changed 回调更新状态输入框读取状态 .clone() 作为显示内容属于单向数据流模式。默认单行模式按下Enter不会插入换行可以用来做提交确认。可以配置多行模式按下Enter直接插入换行。支持占位提示文字、回车事件回调。二、函数签名pubfntext_inputF,State,Action(contents:String,on_changed:F,)-TextInputState,ActionwhereF:Fn(mutState,String)-ActionSendSyncstatic,参数说明contents: String 输入框显示的当前文本必须clone状态里的字符串。on_changed 回调用户输入修改内容时触发参数为 (mut State,新字符串) 在这里更新你的状态字段。常用链式方法.placeholder(“提示文字”)输入为空时显示的占位提示文本。.insert_newline(InsertNewline::OnEnter)按下Enter直接换行开启多行输入。.insert_newline(InsertNewline::OnShiftEnter)ShiftEnter才换行普通Enter用来触发提交是TodoMVC示例的标准写法。.on_enter(|state, _| {})按下Enter键触发回调适合表单提交、新增任务。.flex(1.0)放在 flex_row 布局里使用让输入框占满剩余宽度避免被裁剪。枚举 InsertNewline 需要导入 use xilem::InsertNewline;三、最简基础用法单行输入// state.content 是AppState内的String字段text_input(state.content.clone(),|s:mutAppState,new_text|{s.contentnew_text;}).placeholder(请在这里输入内容);四、两种模式示例代码片段1.单行输入默认Enter用于提交text_input(state.msg.clone(),|s,val|s.msgval).placeholder(单行输入按回车提交).on_enter(|s:mutAppState,_|{// 回车提交业务逻辑});2.多行输入Enter直接换行usexilem::InsertNewline;text_input(state.multiline_text.clone(),|s,val|s.multiline_textval).placeholder(多行文本框按Enter换行).insert_newline(InsertNewline::OnEnter);3.常用Todo模式Enter提交ShiftEnter换行text_input(state.task.clone(),|s,val|s.taskval).placeholder(输入待办回车添加任务ShiftEnter换行).insert_newline(InsertNewline::OnShiftEnter).on_enter(|s:mutAppState,_|{// 添加待办});五、完整可运行DemoCargo.toml[package] name xilem_lesson33_textinput version 0.1.0 edition 2021 [dependencies] xilem 0.4.0 winit 0.30src/main.rsusexilem::winit::error::EventLoopError;usexilem::view::{flex_col,flex_row,label,prose,text_button,text_input};usexilem::{EventLoop,InsertNewline,WidgetView,WindowOptions,Xilem};#[derive(Default)]structAppState{single_line:String,multi_line:String,submit_log:String,}fnapp_logic(state:mutAppState)-implWidgetViewAppStateuse{flex_col((label(第33课 text_input 文本输入框),label(单行输入框回车触发提交),flex_row((text_input(state.single_line.clone(),|s:mutAppState,new_val|s.single_linenew_val,).flex(1.0).placeholder(请输入单行内容回车提交).on_enter(|s:mutAppState,_|{s.submit_log.push_str(format!(提交单行{}\n,s.single_line));s.single_line.clear();}),text_button(手动提交,|s:mutAppState|{s.submit_log.push_str(format!(按钮提交{}\n,s.single_line));s.single_line.clear();}),)),label(多行输入框Enter直接换行),text_input(state.multi_line.clone(),|s:mutAppState,new_val|s.multi_linenew_val,).placeholder(多行文本按Enter换行).insert_newline(InsertNewline::OnEnter),label(提交日志可复制),prose(state.submit_log),)).padding(12.0)}fnmain()-Result(),EventLoopError{letappXilem::new_simple(AppState::default(),app_logic);app.run(EventLoop::with_user_event(),WindowOptions::default())}六、高频踩坑清单必须 .clone() 状态字符串传给text_input第一个参数不能直接移动所有权否则会编译报错或者UI异常。输入框内容完全由状态驱动不要写死常量字符串否则无法编辑。在 flex_row 中使用输入框务必加上 .flex(1.0) 否则输入框宽度不会自动填充会被裁剪显示不全。默认单行模式Enter键不会换行只会触发 .on_enter() 回调。想要换行必须设置 .insert_newline() 。InsertNewline::OnShiftEnter 普通Enter提交ShiftEnter换行适合待办列表场景。0.4版本没有直接设置输入框背景色的公开API可以修改文字颜色、光标颜色、占位文字颜色背景跟随系统主题。text_input 只处理字符串如果需要数字输入要自己在回调中做字符串转数字解析。七、课后练习题 标准答案 逐行解读练习1基础需求创建单行输入框placeholder提示文字为 请输入你的昵称 下方label实时同步显示输入框的内容。参考答案#[derive(Default)]structAppState{nickname:String,}fnapp_logic(state:mutAppState)-implWidgetViewAppStateuse{flex_col((text_input(state.nickname.clone(),|s:mutAppState,new_val|s.nicknamenew_val,).placeholder(请输入你的昵称),label(format!(你的昵称{},state.nickname)),))}详细解读状态 nickname:String 保存输入框文本。第一个参数传入 state.nickname.clone() 把状态副本给到输入框。用户打字触发回调更新状态 nickname 。label读取同一个状态实现实时同步预览。.placeholder() 在字符串为空时显示灰色提示文字。练习2进阶需求多行文本输入框Enter直接换行增加按钮点击按钮把多行输入框全部内容追加到prose日志区然后清空输入框。参考答案usexilem::InsertNewline;#[derive(Default)]structAppState{note:String,log:String,}fnapp_logic(state:mutAppState)-implWidgetViewAppStateuse{flex_col((label(多行笔记输入框),text_input(state.note.clone(),|s:mutAppState,val|s.noteval,).placeholder(写笔记Enter换行).insert_newline(InsertNewline::OnEnter),text_button(保存笔记并清空,|s:mutAppState|{s.log.push_str(format!(笔记\n{}\n,s.note));s.note.clear();}),label(已保存笔记日志可复制),prose(state.log),))}详细解读.insert_newline(InsertNewline::OnEnter) 开启多行按Enter插入换行符。点击按钮把 note 内容追加进 log 调用 .clear() 清空输入框状态。prose展示日志支持鼠标选中复制全部笔记。修改state视图自动刷新输入框与日志区。练习3拓展需求输入框实现待办新增功能输入框placeholder 输入待办任务回车添加任务行为普通Enter添加任务ShiftEnter允许换行写多行任务描述按下回车或点击按钮将输入内容追加日志清空输入框参考答案usexilem::InsertNewline;#[derive(Default)]structAppState{todo_input:String,todo_log:String,}fnapp_logic(state:mutAppState)-implWidgetViewAppStateuse{flex_col((flex_row((text_input(state.todo_input.clone(),|s:mutAppState,val|s.todo_inputval,).flex(1.0).placeholder(输入待办任务回车添加任务).insert_newline(InsertNewline::OnShiftEnter).on_enter(|s:mutAppState,_|{if!s.todo_input.is_empty(){s.todo_log.push_str(format!(- {}\n,s.todo_input));s.todo_input.clear();}}),text_button(添加任务,|s:mutAppState|{if!s.todo_input.is_empty(){s.todo_log.push_str(format!(- {}\n,s.todo_input));s.todo_input.clear();}}),)),label(待办列表),prose(state.todo_log),))}详细解读InsertNewline::OnShiftEnter ShiftEnter换行普通Enter触发 .on_enter() 提交任务。.flex(1.0) 使输入框在flex‑row占满剩余宽度。提交前判断 !s.todo_input.is_empty() 避免空任务写入日志。回车回调与按钮执行完全相同业务逻辑UI交互入口分离状态统一。提交完成调用 .clear() 清空输入框状态。思考题问题为什么 text_input 第一个参数要传入 .clone() 而不是直接传入 state.content 引用标准答案解读Xilem视图是短暂临时对象视图不能长期持有对AppState的引用。text_input 内部需要持有一份当前显示的字符串副本所以需要clone得到自有所有权的String。当用户输入 on_changed 回调把新字符串写回AppState下一次渲染传入新clone副本完成数据流闭环。这是Xilem单向数据流的典型模式状态源在AppState视图拿到副本展示用户修改后回调写回状态。八、知识点总结text_input(content.clone(),on_changed) 用户可编辑输入框内容必须存储在AppState中第一个参数clone状态字符串。默认单行模式Enter不换行触发 .on_enter() 回调通过 InsertNewline 枚举配置换行行为。.placeholder() 设置空输入时的占位提示flex‑row布局务必加 .flex(1.0) 防止裁剪。三种换行策略OnEnter 按Enter直接换行适合大段多行文本。OnShiftEnter Enter提交ShiftEnter换行适合待办、聊天输入框。on_enter() 捕获回车按键用于表单提交按钮与回车回调可以复用同一套业务逻辑。text_input只处理字符串数字需要手动解析转换背景样式跟随主题0.4版本无直接修改背景色API。数据流范式状态为唯一数据源 → 视图clone副本展示 → 用户交互回调写回状态 → UI自动更新。