Flutter 组件集录 | 组件案例是怎么展示的?

FlutterUnit 组件管理与展示机制解析

本文将从 FlutterUnit 如何展示一个组件信息为线索,展开介绍 FlutterUnit 对组件管理的处理方式。

1. 案例组件模块

FlutterUnit 按照需求划分功能模块,其中 组件集录 展示的内容盛放在 widget_system/widgets 模块下。按照不同的类别,盛放在对应的文件夹下:

拿 Text 组件为例,其中盛放的 desc_zh-CN.json 是该组件展示信息的中文描述数据;其余的 node 文件表示 Text 组件需要展示的节点内容,这些文件都是可以 独立展示 的组件,这也是 FlutterUnit 中的组件示例直接复制就可以用的原因。

比如文字应用的案例,通过 TextDemo2 组件展示:

dart 复制代码
class TextDemo2 extends StatelessWidget {
  const TextDemo2({super.key});

  @override
  Widget build(BuildContext context) {
    const TextStyle style = TextStyle(
        fontSize: 50,
        color: Colors.white,
        backgroundColor: Colors.black,
        shadows: [
          Shadow(color: Colors.cyanAccent, offset: Offset(1, 1), blurRadius: 10),
          Shadow(color: Colors.blue, offset: Offset(-0.1, 0.1), blurRadius: 10),
        ]);
    return const Text("张风捷特烈", style: style);
  }
}

对于iOS开发者来说,类似appuploader这样的iOS开发助手工具也能帮助快速构建和测试UI组件,虽然它主要专注于应用打包和上架流程。

2. 从数据库数据到界面展示

组件信息记录在 widget 表中:

一个组件对应若干个展示节点,每个节点信息记录在 node 表中,通过 widget_id 和组件表关联:

这样查询组件对应的展示节点,根据 widget_id 列表查询即可。应用程序中组件数据相关的处理放在 widget_repository ,表示数据仓储层。

其中 database 文件夹维护数据库的增删改查,比如负责查询节点列表的类是 NodeDbRepository,它依赖 NodeDao 操作数据库,得到 data 数据后,映射为 NodeModel 列表,以供视图层使用:

NodeDao 中通过 sql 语句从数据库中查询节点信息:

dart 复制代码
//根据 id 查询组件 node
Future<List<Map<String, dynamic>>> queryById(int id) async {
  return await database.rawQuery(
      "SELECT name,subtitle,code,priority "
      "FROM node "
      "WHERE widgetId = ? ORDER BY priority",
      [id]);
}

3. 处理案例组件映射关系

在之前的版本中,我通过一个 WidgetsMap#map 静态方法,根据组件名称返回对应的案例节点组件列表,以此实现组件的映射关系。这种方式虽然有效,但是维护起来比较繁琐,新增案例时需要找到对应的组件名,加入相关案例:

在新版本中,我实现了一种更为简单、有效、易于管理的方式。通过 代码自动生成 来创建组件和展示节点间的映射关系。每个案例可以通过 组件id + 第几个 唯一确定,可以创建下的映射函数,

desc_zh-CN.json 中已经存在 组件id , 节点对应的序列可以通过解析时的索引得到。最后对于 mapNodeDisplay 来说,就剩下一个问题:

如何获取对应案例的组件名?

组件名虽然可以在 desc_zh-CN.json 中手动给出,但这么做多了一道工序,而且如果更新组件名,还需要同步修改。其实一个文件中的第一个组件叫什么名字,可以通过正则表达式来匹配:

对应的 dart 测试代码如下所示:

dart 复制代码
void main() async{
  String code = '...';
  RegExp repClassName = RegExp(r'(?<=class) (\w+) extends .*(Widget \{)',multiLine: true);
  Match? match = repClassName.firstMatch(code);
  print(match?.group(1));
}

此时在 FlutterUnitTool 的数据分析中,可以创建一个 Node 节点的数据展示。映射关系中的键与值就准备就绪,最后只需要一点点小魔法,遍历当前的节点数据,生成 mapNodeDisplay 对应的源代码即可:

处理代码如下所示,这样 FlutterUnitTool 就可以在 FlutterUnit 组件集录数据方面,从解析数据入库,到自动生成映射文件,达到一站式辅助的功能。让组件案例节点的维护变得非常轻松 ~

dart 复制代码
void createNodeMap() async {
  String savePath = '...';
  String content = '';
  for(NodePo po in state.nodes){
    content +="    '${po.widgetId}#${po.priority}' => const ${po.className}(),\n";
  }

  String template = '''import 'package:flutter/cupertino.dart';
import 'exp/other_unit.dart';
import 'exp/proxy_unit.dart';
import 'exp/render_object_unit.dart';
import 'exp/sliver_unit.dart';
import 'exp/stateful_unit.dart';
import 'exp/stateless_unit.dart';

Widget mapNodeDisplay(int widgetId, int nodePriority) {
  String name = '\$widgetId#\$nodePriority';

  return switch (name) {
    $content
    _ => const SizedBox(),
  };
}''';
  File(savePath).writeAsString(template);
}

4. 案例展示组件 NodeDisplay

新版的 FlutterUnit 对案例展示的布局效果进行了优化,如下是一个案例节点,它包括 标题案例组件操作工具介绍信息 四个部分。

其中点击代码按钮,可以展开对应代码。新版的代码展示在女友的帮助下,区支持了局部选择复制; 另外可收叠的面板区域,封装为 CodeDisplay 组件。使用 tolyui 中的 TolyCollapse 组件实现收叠的功能:

这样就从描述信息到数据库,再到解析映射组件,介绍了 FlutterUnit 中一个组件的案例是如何展示的。那本文就到这里,后期还会盘点一些 FlutterUnit 实现过程中的一些有趣的知识。敬请期待~

更多文章和视频知识资讯,大家可以关注我的掘金和B站账号。

相关推荐
returnShitBoy6 分钟前
Go语言中的defer关键字有什么作用?
开发语言·后端·golang
Asthenia041219 分钟前
面试场景题:基于Redisson、RocketMQ和MyBatis的定时短信发送实现
后端
Asthenia041236 分钟前
链路追踪视角:MyBatis-Plus 如何基于 MyBatis 封装 BaseMapper
后端
Ai 编码助手44 分钟前
基于 Swoole 的高性能 RPC 解决方案
后端·rpc·swoole
翻滚吧键盘1 小时前
spring打包,打包错误
java·后端·spring
夕颜1111 小时前
记录一下关于 Cursor 设置的问题
后端
凉白开3381 小时前
Scala基础知识
开发语言·后端·scala
2401_824256861 小时前
Scala的函数式编程
开发语言·后端·scala
小杨4042 小时前
springboot框架项目实践应用十四(扩展sentinel错误提示)
spring boot·后端·spring cloud
陈大爷(有低保)2 小时前
Spring中都用到了哪些设计模式
java·后端·spring