【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,框架对比新旧视图树,增量更新列表条目,实现动态增减列表。

相关推荐
sunshine22 girl5 小时前
Java学习六 Java常见API-2--String-3-字符串的截取替换和其他方法
java·开发语言·学习
sunshine22 girl6 小时前
Java学习六 Java常见API-1-Radom随机数
java·开发语言·学习
Answer1st6 小时前
【嵌入式学习】嵌入式原理知识-DMA(九)
学习
传奇开心果编程7 小时前
【ArkUI进阶练中学】第11课:安全与合规进阶
学习·ui·华为·harmonyos
Mr_Macallon9 小时前
C++回顾(基础)(01)
c语言·开发语言·c++·学习
sunoo-22910 小时前
【ARM嵌入式学习笔记第十天】i.MX6ULL eLCDIF控制器驱动RGB LCD全解析(硬件原理+寄存器配置+裸机代码)
arm开发·笔记·学习
kaiyou202610 小时前
用户研究岗秋招,统计分析能力怎么学习和证明?
数据库·python·学习
知识分享小能手10 小时前
C++ 学习教程,从入门到精通,string类和标准模板库 — 完整知识点详解(16)
开发语言·c++·学习
inferno12 小时前
SVN学习笔记(二)
笔记·学习·svn