前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >nicegui功能代码基本组织方式

nicegui功能代码基本组织方式

作者头像
咋咋
发布2024-04-28 15:05:56
1360
发布2024-04-28 15:05:56
举报
文章被收录于专栏:数据大宇宙数据大宇宙

前面的章节我们已经学习了大部分的布局知识,接下来我们将重点学习功能实现。

本节我们将以一个简单的 todo list 为实战,讲解在 nicegui 中最基础的功能代码组织方式。

本节尽可能避免过多的布局和样式代码

本节我们将学会:

  • 如何简单分离界面与核心逻辑代码
  • 通过刷新局部区域,更新界面

本节使用的 nicegui 版本为 1.4.22


界面与功能代码分离

从一个简单信息提交的功能开始。

  • 用户填写好信息后,点击提交按钮
  • 上方出现结果信息

看看流程图:

与代码对照看:

  • 行20-26:这里是界面内容的代码,尽可能让这里的代码能够与界面内容对应上,不要混入其他逻辑的代码。比如点击事件的处理函数,应该放在其他的地方
  • 行10-18:点击按钮时的事件处理。
  • 行11-12:收集界面上的数据。
  • 行15: 这里是关键!我们必须保证事件处理逻辑简单,特别是与界面无关的逻辑,不要直接写到这里。因此,我们通过调用一个 save_data 函数,把逻辑转移出去。 利用函数的入参和返回值,完成模块之间的通信
  • 行18:把返回值显示。

经常有人问我,怎么用 nicegui 做一个数据库的增删改查界面?大家想想,上面第15行代码中的函数 save_data ,里面的代码到底怎么写?如果我告诉你,它里面就是把数据写入数据库,你觉得有可能吗?

实际上,它的代码是这样:

是的,对于界面代码来说,这个函数里面的代码逻辑不重要。界面根本不关心到底是不是把数据写入了数据库。

现在我们可以非常简单测试出界面代码是否正确。

注意,这个函数里面完全不会用到任何与界面相关的东西。所以函数的参数只能是基础类型。千万别因为偷懒,而把组件对象直接传进来。

因此,我们必须学会把界面逻辑与业务逻辑分离。

什么才算是界面逻辑?

  1. 界面内容改变。比如,上面例子中的 label 显示提交信息
  2. 界面样式变化。比如,要求提交按钮只有在两个输入框都有内容时,才可以被点击

现在看看怎么实现第二点:

  • 行31:我们需要在其他的事件中使用按钮,得定义变量"接住"按钮对象
  • 行32:一开始禁用按钮
  • 行28-29:绑定两个输入框的变化事件
  • 行21-22:输入框变化的事件处理函数。通过两个输入框内容设置按钮可用状态

这就是最普通最基础的方式,基于事件实现交互。这不是 nicegui 独有的方式,任何界面框架都离不开这种模式。


基于这种写法,现在可以构建 todo list 中,新增任务的界面和功能:

下面是界面逻辑:

  • 行20:add_todo 是业务模块的函数

下面是业务模块的代码:

  • 行4:用一个列表保存 todo 任务
  • 行8:新增一个任务的函数。这就是界面模块调用的入口

这里为了方便演示,用了全局变量并且业务代码与界面代码写在同一个文件。你当然可以通过定义类等方式组织代码

当我们添加了一个 todo 任务后,下方应该显示当前所有的任务信息。接下来我们将应用 nicegui 特有的页面局部区域刷新功能完成。


区域刷新

按直觉来说,代码应该如下:

  • 行37-41:遍历任务列表,创建每一行的组件即可

但是很显然是不行。在以前关于事件的章节中我们已经了解到,只有事件处理函数的代码才会不断执行。而这里的任务列表(变量 g_todos),随着用户操作不断变化。

在容器的章节中,我们知道,容器可以增删改里面的元素。所以我们稍微修改一下:

  • 行28-35:把遍历任务列表的过程提取出来
  • 行29:每次执行,先清空容器
  • 行47-48:页面首次加载,得调用一下(因为有可能第一次访问,就有以前保留的任务列表)

当然,我们还需要在所有影响任务列表的事件处理中,调一下函数 create_todo_items

现在界面显示已经没问题:

但是我们的界面代码不够好,nicegui 内置了一个"刷新"装饰器:

  • 行40: @ui.refreshable 装饰器打在自定义函数。
  • 行42-46:还是之前的逻辑,但是,不需要清空容器。
  • 行49:初始化的时候,还是需要调用一次函数

在点击按钮的时候,我们不能再次调用函数,改成调用函数对象的 refresh 方法:

这是因为只有调用 refresh 方法,才是清空容器。如果直接调用函数本身,则会重新创建了一个"刷新区域"

下面是一个简单示意图:

  • 如果多次调用函数(上图绿色部分),则会创建多个独立的区域
  • 一旦调用函数的 refresh 方法,则会触发所有的区域进行刷新(上图红色部分)

总结一下:

  1. 在自定义函数上打装饰器 @ui.refreshable
  2. 在需要构建刷新区域的地方,调用函数
  3. 在需要刷新的时候,调用函数对象的 refresh 方法

@ui.refreshable 还有广播能力,后续的章节再展开说明


接下来看看任务删除的功能:

  • 行53:每个 todo 都是一个字典,从字典取出 id 。

这里简单说一下,直觉上你可能认为下面的代码没问题:

实际上,每个按钮的事件中,获得的 todo 总是列表中的最后一个。

我们只需要搞清楚,上面代码,哪些代码是在循环中立刻执行,哪些代码是延迟执行,就知道该怎么写:

  • 紫色部分的代码,是循环中立刻执行。所以,id 参数就是当前 todo 的 id 值
  • 红色部分的代码,不是在循环中执行,而是循环结束后,用户点击按钮才执行。此时,里面的 todo 就会是遍历结束后的值(列表最后一项)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据大宇宙 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 界面与功能代码分离
  • 区域刷新
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档