【xilem0.4基础语法学与练】第48课 lists组件官方示例代码深度解析

前言

源码来源:xilem/examples/lists.rs

适配版本:Xilem 0.4 / Masonry 0.4

一、官方完整源码

rust 复制代码
  
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0

//! Displaying a variable length list is achieved using a [Vec] `FlexSequence`.

use winit::error::EventLoopError;
use xilem::view::{MainAxisAlignment, flex_col, prose, text_button};
use xilem::{EventLoop, WidgetView, WindowOptions, Xilem};

#[derive(Default)]
struct AppState {
    count: usize,
}

fn app_logic(state: &mut AppState) -> impl WidgetView<AppState> + use<> {
    // A vector (Vec) of views can be used as part of a `flex`'s children, allowing collections of dynamic length to be displayed.
    let list = (0..state.count)
        .map(|n| prose(format!("item #{n}")))
        .collect::<Vec<_>>();

    flex_col((
        // Even when a `Vec` is used for the children, other widgets can be included by putting them in a
        // tuple of children alongside the vector.
        text_button("more", |appstate: &mut AppState| appstate.count += 1),
        list,
    ))
    // We can control alignment of the elements in the flexbox
    .main_axis_alignment(MainAxisAlignment::Start) // Aligned to the left
}

fn main() -> Result<(), EventLoopError> {
    let app = Xilem::new_simple(AppState::default(), app_logic, WindowOptions::new("Lists"));
    app.run_in(EventLoop::with_user_event())?;
    Ok(())
}
 

二、程序核心功能

本示例演示 动态变长列表(FlexSequence):

  • 点击 more 按钮,count 计数 +1
  • 根据 count 动态生成列表条目 item #0 、 item #1 ......
  • 核心特性: flex_col 支持将 Vec 视图集合直接作为子元素,实现动态数量视图渲染
  • 不需要循环组件、不需要宏,纯链式 Builder 写法

核心概念:FlexSequence

在 Xilem0.4 中,当把 Vec 放入 flex 的子元组,会自动识别为 FlexSequence ,用于渲染长度会变化的视图序列。

三、逐模块深度解析

1. AppState 状态结构体

rust 复制代码
  
#[derive(Default)]
struct AppState {
    count: usize,
}
 
  • count: usize :记录列表条目总数,无符号自然数,初始默认值为0
  • #derive(Default) :自动实现 Default trait,初始化时 count=0

2. 动态列表生成

rust 复制代码
  
let list = (0..state.count)
    .map(|n| prose(format!("item #{n}")))
    .collect::<Vec<_>>();
 
  1. (0...state.count) :Rust 标准区间迭代器,生成 0,1,2,...,count-1
  2. .map(|n| prose(...)) :每一个序号生成一段文本视图 prose
  3. .collect::<Vec<_>>() :收集所有视图,打包成 Vec 视图数组
  • prose() :Xilem 的文本组件,用于展示普通段落文字

3. flex_col 混合子元素(重点)

rust 复制代码
  
flex_col((
    text_button("more", |appstate: &mut AppState| appstate.count += 1),
    list,
))
 

关键知识点:

flex 的子元素元组可以混合普通组件 + Vec视图数组

  • 元组第一项:普通组件 text_button (固定存在的按钮)
  • 元组第二项: Vec 动态视图集合(条目数量随状态改变)
    Xilem 内部自动把 Vec 转为 FlexSequence,支持动态增减条目
rust 复制代码
  
.main_axis_alignment(MainAxisAlignment::Start)
 
  • flex_col 垂直布局,主轴为垂直方向
  • MainAxisAlignment::Start :子元素靠顶部对齐

4. app_logic 与更新机制

app_logic 是视图构建函数,每次状态变更都会重新执行

  1. 用户点击按钮 → count +=1
  2. 状态更新,再次运行 app_logic
  3. 重新生成新的 list(条目数量+1)
  4. Xilem diff 新旧视图树,只增量新增对应的 item 视图

注意:

这个基础示例没有做虚拟滚动,条目极多的时候性能会下降。大量长列表需要搭配 portal(滚动容器)。

5. main 入口

rust 复制代码
 
let app = Xilem::new_simple(AppState::default(), app_logic, WindowOptions::new("Lists"));
app.run_in(EventLoop::with_user_event())?;
  • new_simple :快速创建简单应用,传入初始状态、视图逻辑、窗口配置
  • 窗口标题: Lists

四、生产级拓展代码

拓展1:增加减少按钮,支持删减列表项

rust 复制代码
 
fn app_logic(state: &mut AppState) -> impl WidgetView<AppState> + use<> {
   let list = (0..state.count)
       .map(|n| prose(format!("item #{n}")))
       .collect::<Vec<_>>();

   flex_col((
       flex_row((
           text_button("more", |appstate: &mut AppState| appstate.count += 1),
           text_button("less", |appstate: &mut AppState| {
               if appstate.count > 0 {
                   appstate.count -= 1;
               }
           }),
       )),
       list,
   ))
   .main_axis_alignment(MainAxisAlignment::Start)
}

拓展2:套入 portal,实现长列表滚动

rust 复制代码
 
fn app_logic(state: &mut AppState) -> impl WidgetView<AppState> + use<> {
   let list = (0..state.count)
       .map(|n| prose(format!("item #{n}")))
       .collect::<Vec<_>>();

   let content = flex_col((
       text_button("more", |appstate: &mut AppState| appstate.count += 1),
       list,
   ))
   .main_axis_alignment(MainAxisAlignment::Start);

   portal(content)
}

五、本课核心知识点总结

  1. Xilem 0.4 的 flex 布局支持元组内混合普通组件 + Vec动态视图序列(FlexSequence),用来实现动态列表。
  2. prose 是基础文本组件,用于展示段落文本。
  3. 状态变化会重新执行 app_logic ,重新生成 Vec 列表,框架自动 diff 视图做增量更新。
  4. 基础动态列表无虚拟滚动,数据量大时,需要配合 portal 滚动容器。
  5. flex_col 的 MainAxisAlignment::Start 代表主轴起始位置对齐,垂直列表默认置顶。

六、课后习题

练习1 填空

  1. Xilem0.4 中,把视图集合存入Vec放入flex子元组,会自动识别为 ________。
  2. prose 组件的作用是 ________。
  3. 本示例列表条目数量保存在状态字段 ________。
  4. 长列表需要滚动,要使用 ________ 组件包裹内容。

填空题参考答案

  1. FlexSequence
  2. 展示段落文本
  3. count
  4. portal

练习2 判断

  1. flex_col 的子元组,可以同时放置普通组件和Vec视图数组。(✅正确)
  2. 本示例自带虚拟滚动,支持上万条数据无性能损耗。(❌错误)
  3. 每次点击more按钮,状态更新后app_logic会重新执行。(✅正确)
  4. MainAxisAlignment::Start 在 flex_col 代表子元素靠顶部对齐。(✅正确)

练习3 简答

题目:FlexSequence 动态列表的实现原理是什么?

简答题参考答案

将迭代生成的多个视图收集为 Vec ,放入flex布局的子元素元组,Xilem自动识别为FlexSequence;状态变更时app_logic重新生成新Vec,框架对比新旧视图树,增量更新列表条目,实现动态增减列表。

相关推荐
传奇开心果编程5 小时前
【Rust入门知识点学与练】第24课:Trait 基础
开发语言·学习·rust
潜心一志9 小时前
HALCON软件——基本架构,算子参数
学习·计算机视觉
爱吃苹果的日记本11 小时前
数据结构第三课(时间复杂度)
数据结构·学习
泡泡鱼(敲代码中)14 小时前
MySQL基础学习笔记:从数据模型到DDL全掌握
开发语言·数据库·笔记·学习·mysql
fanged15 小时前
Agent的Skills(TODO)
学习
是隼人15 小时前
buuctf-pwn picoctf_2018_shellcode(ret2shellcode)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
m4Rk_15 小时前
【论文阅读】Agent 记忆机制(69):STITCH——用上下文意图解决“语义相关但情境错误”的记忆检索
论文阅读·人工智能·学习·开源·github
2601_9499506315 小时前
个人在线刷题的工具
学习·考研·小程序·刷题·小程序推荐
一尘之中16 小时前
深入解析面向服务的架构(SOA):从特性到实施
学习·架构·ai写作