ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

【dioxus0.7基础语法学与练】第2课:条件渲染与列表渲染

【dioxus0.7基础语法学与练】第2课:条件渲染与列表渲染 学习目标本课解决两个问题根据条件决定显示什么以及根据数据批量生成 UI。知识点1条件渲染 — if最简单的场景满足条件才显示某段 UI。usedioxus::prelude::*;#[component]fnIfDemo()-Element{letis_logged_inuse_signal(||true);rsx!{// if 为真时渲染内部内容为假时什么都不渲染ifis_logged_in(){div{class:welcome,欢迎回来}}}}注意if 后面直接跟 { } 花括号里面写 rsx! 的内容不需要再套一层 rsx!。知识点2条件渲染 — if / else二选一满足条件显示 A否则显示 B#[component]fnIfElseDemo()-Element{letis_vipuse_signal(||false);rsx!{ifis_vip(){div{class:vip,VIP 专属内容}}else{div{class:normal,普通用户内容}}}}知识点3条件渲染 — if / else if / else多分支根据不同条件显示不同内容。#[component]fnMultiBranchDemo()-Element{letroleuse_signal(||editor);rsx!{ifrole()admin{div{管理员面板}}elseifrole()editor{div{编辑面板}}else{div{访客面板}}}}知识点4条件渲染 — 提前计算 Element当条件逻辑较复杂时可以先在 Rust 代码中计算出 Element再插入 rsx!#[component]fnPreComputeDemo()-Element{letstatususe_signal(||404);rsx!{div{{letelementmatchstatus(){200rsx!{p{页面正常}},404rsx!{p{页面未找到}},500rsx!{p{服务器错误}},_rsx!{p{未知状态}},};element}}}}用 { } 包裹一个 Rust 代码块代码块的最后一个表达式作为渲染结果插入。知识点5列表渲染 — for 循环根据数据集合批量生成 UI 节点。#[component]fnForDemo()-Element{letfruitsvec![苹果,香蕉,橙子];rsx!{ul{forfruitinfruits{li{key:{fruit},// key 帮助 diff 算法识别元素身份{fruit}}}}}}key 属性的作用列表重排、增删时Dioxus 用 key 判断哪个节点是哪个没有 key按位置对比重排后状态可能错乱有 key按标识对比状态正确保留规则key 的值在列表中必须唯一知识点6列表渲染 — 带索引和复杂逻辑#[component]fnForAdvancedDemo()-Element{letitemsvec![Rust,Dioxus,WASM];rsx!{// 带索引 ol{for(index,item)initems.iter().enumerate(){li{key:{item},第 {index} 项{item}}}}// 循环体中做复杂计算 div{foriteminitems{{letlabelformat!( {},item.to_uppercase());rsx!{span{key:{item},{label} }}}}}// 迭代器直接渲染不用 for 语法div{{(0..5).map(|i|rsx!{span{key:{i}, {i} }})}}}}两种列表渲染写法对比写法 语法 适用场景for 循环 for item in iter { … } 大多数场景可读性好迭代器表达式 {iter.map(… )} 需要链式调用filter、enumerate 等知识点7条件 列表组合实际开发中条件和列表经常组合使用#[component]fnCombinedDemo()-Element{letshow_listuse_signal(||true);letitemsvec![任务A,任务B,任务C];rsx!{div{ifshow_list(){// 条件为真时渲染列表ul{foriteminitems{li{key:{item},{item}}}}}else{p{列表已隐藏}}}}}核心规则概念 说明if 条件为真时渲染为假时不渲染if / else 二选一渲染if / else if / else 多分支渲染提前计算 Element 用 match 或 if 在 Rust 代码中算好 Element用 { } 插入for 循环 for item in iter { li { key: “…”, … } }key 列表项唯一标识帮助 diff 正确识别节点迭代器渲染 {iter.map(\ x\ rsx! { … })} 写法动手试试补全下面的代码usedioxus::prelude::*;fnmain(){dioxus::launch(App);}#[component]fnApp()-Element{rsx!{div{style:padding: 20px; font-family: sans-serif;,// 题目1登录状态显示 LoginDisplay{}hr{}// 题目2成绩等级 GradeDisplay{}hr{}// 题目3动态购物清单 ShoppingList{}}}}// 题目1登录状态显示 // 要求// - 用 use_signal 存储 is_logged_in初始值 false// - 用 use_signal 存储 username初始值 游客// - 如果已登录显示 欢迎{username} 和一个 退出 按钮// - 如果未登录显示 请先登录 和一个 登录 按钮// - 点击 登录 按钮is_logged_in 设为 trueusername 设为 张三// - 点击 退出 按钮is_logged_in 设为 falseusername 设为 游客#[component]fnLoginDisplay()-Element{// 补全todo!()}// 题目2成绩等级 // 要求// - 用 use_signal 存储 score初始值 75// - 根据分数显示等级用 if / else if / else// - 90 及以上 → 优秀 // - 70~89 → 良好 // - 60~69 → 及格 ✅// - 60 以下 → 不及格 ❌// - 显示当前分数和对应等级// - 提供 10 和 -10 按钮调整分数#[component]fnGradeDisplay()-Element{// 补全todo!()}// 题目3动态购物清单 // 要求// - 用 use_signal 存储商品列表 VecString// 初始值vec![牛奶.into(), 面包.into(), 鸡蛋.into()]// - 用 for 循环渲染商品列表每项带 key// - 每项后面有 删除 按钮点击后从列表中移除该商品// - 底部显示 共 N 件商品// - 如果列表为空显示 购物车是空的用 if 判断#[component]fnShoppingList()-Element{// 补全todo!()}期望效果题目1初始显示请先登录和登录按钮点击登录后切换为欢迎张三和退出按钮题目2初始 75 分显示良好 点击 10 变为 85 仍为良好再加 10 变为 95 显示优秀 题目3初始显示 3 件商品可逐个删除删完后显示购物车是空的写好了贴过来没问题就进入第3课组件 Props 与组件通信 贴代码Dioxus‑0.7 完整参考答案Cargo.toml[package] name dioxus-lesson version 0.1.0 edition 2021 [dependencies] dioxus 0.7完整源码usedioxus::prelude::*;fnmain(){dioxus::launch(App);}#[component]fnApp()-Element{rsx!{div{style:padding: 20px; font-family: sans-serif;,// 题目1登录状态显示 LoginDisplay{}hr{}// 题目2成绩等级 GradeDisplay{}hr{}// 题目3动态购物清单 ShoppingList{}}}}// 题目1登录状态显示 #[component]fnLoginDisplay()-Element{letmutis_logged_inuse_signal(||false);letmutusernameuse_signal(||游客.to_string());rsx!{div{style:padding:10px;border:1px solid #ccc;border-radius:6px;,ifis_logged_in(){p{欢迎{username}}button{onclick:move|_|{is_logged_in.set(false);username.set(游客.to_string());},退出}}else{p{请先登录}button{onclick:move|_|{is_logged_in.set(true);username.set(张三.to_string());},登录}}}}}// 题目2成绩等级 #[component]fnGradeDisplay()-Element{letmutscoreuse_signal(||75u32);letgradematchscore(){90..u32::MAX优秀 ,70..89良好 ,60..69及格 ✅,_不及格 ❌,};rsx!{div{style:padding:10px;border:1px solid #ccc;border-radius:6px;,p{当前分数{score}}p{等级{grade}}button{onclick:move|_|score10,10}button{onclick:move|_|score-10,style:margin-left:8px,-10}}}}// 题目3动态购物清单 #[component]fnShoppingList()-Element{letmutitemsuse_signal(||vec![牛奶.to_string(),面包.to_string(),鸡蛋.to_string(),]);rsx!{div{style:padding:10px;border:1px solid #ccc;border-radius:6px;,ifitems().is_empty(){p{购物车是空的}}else{ul{for(idx,name)initems().iter().enumerate(){li{key:{idx},{name}button{onclick:move|_|{items.remove(idx);},style:margin-left:8px;color:red,删除}}}}p{共 {items().len()} 件商品}}}}}核心知识点1. 条件渲染if / else 直接写在 rsx! 内部用于登录组件、购物清单空状态2. match模式匹配成绩等级用match做区间判断比多个else‑if更简洁3. use_signal集合操作items.remove(index) 删除数组元素信号自动触发页面刷新4. 列表key循环渲染必须添加key属性Dioxus diff算法需要。
RELATED READING

延伸阅读

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