综合演示:XML 与使用代码动态创建组件演示

文档概述

本示例展示如何使用 XML 定义界面布局,并通过轻语言代码实现组件的动态创建、添加、迁移——把可视化设计中已存在的组件(绝对布局1及其子组件)整体迁移到垂直滚动框中。这是轻语言中「XML 静态布局 + 代码动态生成」混合开发模式的典型范例,也是理解容器视图、组件类型判断、弹性布局转换的关键示例。

💡 本演示的核心价值在于「迁移组件」这一场景:已存在于 .spldg 中的组件可以通过修改 定位移动 等属性后,用 添加组件 重新挂到另一个容器下,实现组件的跨容器移动。

学习目标

阅读本文档后,你应当能够掌握以下内容:

  • 动态创建组件:变量 局_按钮 = 创建 按钮()
  • 动态添加组件到容器:根布局.添加组件(局_按钮) / 垂直滚动框1.添加组件(...)
  • 动态组件的布局参数设置:移动(左边, 顶边, 宽度, 高度) 支持整数与带单位文本
  • 非绝对布局容器中子组件需清空 定位局_按钮对象.定位 = ""
  • 容器子组件遍历:取子组件数() + 取子组件(索引)
  • 组件类型判断:子组件对象 类属 单行输入框
  • 绝对布局转弹性布局:绝对布局1.转为弹性布局("column")
  • 闭包回调注册:置被单击回调((源对象,事件源)=>{...})

涉及组件

本演示实际使用到的组件如下:

组件名称作用参考文档
页面<页面>页面根容器文档框架基础类_页面
绝对布局<绝对布局>(根布局)顶层定位容器文档布局类组件_绝对布局
绝对布局<绝对布局1>待迁移的面板容器(含子组件)文档布局类组件_绝对布局
垂直滚动框<垂直滚动框1>接收迁移组件的滚动容器文档列表类组件_垂直滚动框
标签<标签1>状态显示文档文本类组件_标签
按钮<按钮1> + 动态创建的多个按钮触发迁移 / 动态生成文档文本类组件_按钮
单行输入框<单行输入框1>绝对布局1 的子组件(迁移演示)文档文本类组件_单行输入框
单选框<单选框1>绝对布局1 的子组件文档选择类组件_单选框
多选框<多选框1>绝对布局1 的子组件文档选择类组件_多选框

📌 弹性布局 类虽未在 .spldg 中声明,但通过 转为弹性布局("column") 在运行时把绝对布局1 转换为弹性布局(详见后文「关键代码解读」)。

涉及函数与关键字

以下为本演示代码中出现的轻语言关键字与内置函数:

关键字: 变量事件 ... 结束 事件函数 ... 结束 函数变量循环 ... 结束循环如果 ... 结束 如果创建类属返回

组件创建:

  • 创建 按钮() —— 动态实例化一个按钮组件(返回视图对象)

视图通用方法:

  • 移动(左边, 顶边, 宽度, 高度) —— 一次性设置位置与尺寸,参数可为整数(默认 px)或带单位文本
  • 置被单击回调(回调) —— 设置被单击的回调函数
  • 定位 = "" —— 清空定位,交由父布局接管(用于非绝对布局容器)

容器视图方法(绝对布局、弹性布局、滚动框等均继承):

  • 添加组件(组件) —— 向容器追加一个子组件
  • 取子组件数() —— 取得容器中子组件数量
  • 取子组件(索引) —— 取得指定索引的子组件对象

绝对布局特有方法:

  • 转为弹性布局(方向) —— 将绝对布局转换为弹性布局,参数为方向(如 "column" 纵向、"row" 横向)

运算符:

  • 类属 —— 类型判断运算符,等价于 JavaScript 的 instanceof,如 子组件对象 类属 单行输入框
  • % —— 取余运算符,如 i % 2 == 0 判断奇偶

程序结构与运行流程

本项目由成对的两个文件组成:

demo.spldg   ← 页面布局文件(XML 格式,定义静态组件)
demo.spl     ← 页面逻辑文件(轻语言代码,动态创建与迁移)

运行时流程如下:

  1. 浏览器加载 demo 页面 → 框架解析 demo.spldg 构建静态 DOM(根布局、标签1、垂直滚动框1、按钮1、绝对布局1 及其 3 个子组件)
  2. 执行 demo.spl 中的 页面加载完毕 事件:
    • 动态创建 1 个按钮 → 设置文本、位置、单击回调 → 添加到 根布局
    • 调用 动态批量创建组件() → 在 垂直滚动框1 中循环创建多个按钮
  3. 用户点击「按钮1」(静态按钮)→ 触发 按钮1.被单击 → 将 绝对布局1 整体迁移到 垂直滚动框1
    • 修改 绝对布局1 的定位为 relative、宽度 100%、高度 auto
    • 遍历子组件,清空定位、调整外边距,对单行输入框特判样式
    • 绝对布局1 转为弹性布局(纵向)
    • 绝对布局1 添加到 垂直滚动框1

程序源代码

demo.spldg

<?xml version="1.0" encoding="utf-8"?>
<页面 标题="页面标题" 宽度="628" 高度="496">
  <绝对布局 名称="根布局">
    <标签 名称="标签1" 左边="12" 顶边="108" 高度="40" 宽度="218" 文本="我是最棒的!" 背景颜色="#B8E4C7" />
    <垂直滚动框 名称="垂直滚动框1" 左边="394" 顶边="108" 高度="318" 宽度="219" 背景颜色="#DFE7FB" />
    <按钮 名称="按钮1" 左边="12" 顶边="176" 高度="39" 宽度="120" 文本="动态迁移组件" />
    <绝对布局 名称="绝对布局1" 左边="154" 顶边="176" 高度="134" 宽度="234" 背景颜色="#B8E6B5">
      <单行输入框 名称="单行输入框1" 左边="3" 顶边="5" 高度="34" 宽度="228" />
      <单选框 名称="单选框1" 左边="28" 顶边="45" 高度="36" 宽度="106" 标题="单选框1" />
      <多选框 名称="多选框1" 左边="13" 顶边="87" 高度="40" 宽度="105" 标题="多选框1" />
    </绝对布局>
  </绝对布局>
</页面>

demo.spl

' ****************************************************************************
' 版权说明:Copyright(C) All Rights Reserved VcnStudio
' 程序版本:V1.0
' 程序作者:
' 联系信息:
' 窗口描述:默认首页。
' ****************************************************************************

' 页面变量,整个页面都能使用
变量 页面变量 = "首页"

事件 页面加载完毕()
    ' 这里我们演示创建一个按钮,和循环创建10个按钮添加到滚动框中
    ' 注意:如果可视化设计器窗口中(界面布局文件.spldg)已经添加了名称为“按钮1”的按钮组件,那么在代码中动态创建按钮时
    ' 就不能再取名为“按钮1”
    变量 局_按钮 = 创建 按钮()
    局_按钮.文本 = "我是动态创建的按钮" 
    ' 设置当前创建的按钮布局位置,参数值可以为整数、或文本,当设置含有单位的参数值时,必须为文本类型
    ' 例如:下方的10,20 不带单位时,默认为px像素,如果设置单位则需要使用双引号包裹作为文本参数值设置
    局_按钮.移动(10,20,"50%","60px")
    ' 为按钮设置被单击事件,当按钮在页面中被用户单击后,系统反馈给我们(开发者)
    局_按钮.置被单击回调((源对象,源事件)=>{
        弹出提示("动态创建的按钮被单击")
        标签1.文本 = "动态创建的按钮被单击"
    })
    ' 将按钮添加到根布局或任意其它布局中
    根布局.添加组件(局_按钮)
    ' 除了上述方式外,我们也可以将创建组件的代码放在一个函数中,然后在合适的地方调用函数
    动态批量创建组件()
结束 事件

函数 动态批量创建组件()
    垂直滚动框1.边框圆角 = "4px"
    变量循环(i = 0,10,1)
        变量 局_按钮对象 = 创建 按钮()
        ' 注意:任何添加到父布局为非绝对布局的容器中时,都需要设置定位为空或适合父布局的定位
        ' 设置为指定定位后,由父布局处理子组件的定位模式,这里我们设置其子组件的定位为空
        局_按钮对象.定位 = ""
        ' 设置一下宽高尺寸
        局_按钮对象.宽度 = "100%"
        局_按钮对象.内边距 = "10px"
        局_按钮对象.外边距底 = "10px"
        ' 设置不同索引的颜色背景
        如果(i % 2 == 0)
            局_按钮对象.背景颜色 = "#18b165"
        结束 如果
        ' 设置其它属性
        局_按钮对象.文本 = "动态按钮" + i
        局_按钮对象.置被单击回调((源对象,事件源)=>{
            标签1.文本 = "垂直滚动框中按钮被单击,索引:" + i
        })
        垂直滚动框1.添加组件(局_按钮对象)
    结束循环
结束 函数

事件 按钮1.被单击(源对象,事件源)
    ' 将窗口中的“绝对布局1”(类似面板)连同子组件内容添加到垂直滚动框中
    ' 由于“绝对布局1”本身是放在根布局(绝对定位)中,因此要将其添加到滚动框内之前
    ' 我们需要修改其定位属性及尺寸,由于保护了子组件,我们设置其布局为 相对布局,并修改其宽度
    ' 铺面滚动框、高度自动
    绝对布局1.定位 = "relative"
    绝对布局1.宽度 = "100%"
    绝对布局1.高度 = "auto"
    ' 修改其子组件相关属性
    变量 子组件数量 = 绝对布局1.取子组件数()
    变量循环(i = 0,子组件数量,1)
        变量 子组件对象 = 绝对布局1.取子组件(i)
        ' 调试输出(子组件对象)
        ' 这里返回的子组件对象为视图对象、每个视图对象都拥有视图类所有属性和事件
        ' 设置子组件定位为空、且调整布局参数为空
        子组件对象.定位 = ""
        子组件对象.移动("","","","")
        ' 设置上下外边距为10px、左右外边距为 0px
        子组件对象.外边距 = "10px 0px"
        ' 判断指定类型组件,并设置其属性
        如果(子组件对象 类属 单行输入框)
            子组件对象.内边距 = "6px"
            子组件对象.边框圆角 = "6px"
        结束 如果
        ' 将其转为弹性布局
        绝对布局1.转为弹性布局("column")
    结束循环
    ' 添加到垂直滚动框中
    垂直滚动框1.添加组件(绝对布局1)
结束 事件


关键代码解读

1. 动态创建组件与命名冲突

变量 局_按钮 = 创建 按钮()
局_按钮.文本 = "我是动态创建的按钮"
  • 创建 按钮() 实例化一个按钮视图对象,返回值赋给局部变量 局_按钮
  • 命名冲突注意.spldg 中已声明的组件名(如 按钮1)在页面中已被占用,动态创建时不能再取同名,否则会覆盖原有组件引用
  • 局部变量推荐用 局_ 前缀,与页面级 页_、模块级 程_ 区分

2. 移动方法的参数类型

局_按钮.移动(10,20,"50%","60px")
  • 移动(左边, 顶边, 宽度, 高度) 四个参数均可为整数或文本
  • 整数:默认单位为 px,如 10 等价于 10px
  • 带单位文本:必须用双引号包裹,如 "50%""60px"
  • 若传带单位却不加引号(如 50%)会被当作表达式解析导致错误

3. 非绝对布局容器中的子组件定位

局_按钮对象.定位 = ""
  • 绝对布局的子组件靠 左边/顶边 定位
  • 弹性布局、滚动框等容器靠自身布局算法排列子组件
  • 因此添加到非绝对布局容器前,必须清空子组件的 定位(设为 ""),交由父布局接管
  • 否则子组件会保留绝对定位,脱离父布局的流式排列

4. 组件类型判断:类属运算符

如果(子组件对象 类属 单行输入框)
    子组件对象.内边距 = "6px"
    子组件对象.边框圆角 = "6px"
结束 如果
  • 类属 是轻语言的类型判断运算符,等价于 JavaScript 的 instanceof
  • 用法:对象 类属 类型名,返回逻辑值
  • 这里遍历绝对布局1 的子组件时,对「单行输入框」类型的子组件做特判样式处理
  • 因为 取子组件(i) 返回的是通用 视图 对象,访问子类特有属性前需先判断类型

5. 绝对布局转弹性布局

绝对布局1.转为弹性布局("column")
  • 转为弹性布局(方向) 是绝对布局的特有方法
  • "column" 为纵向排列,"row" 为横向排列
  • 转换后原绝对布局的子组件按弹性布局算法重新排列
  • 注意:本演示中该语句位于 变量循环 内部,会被多次调用。由于转换是幂等的(重复转换无副作用),功能上不会出错,但更合理的写法是将其移到循环外,仅调用一次:
变量循环(i = 0,子组件数量,1)
    ' ...子组件属性调整...
结束循环
' 转换应在循环外,只调用一次
绝对布局1.转为弹性布局("column")

6. 组件迁移的整体流程

' ① 修改容器自身定位与尺寸
绝对布局1.定位 = "relative"
绝对布局1.宽度 = "100%"
绝对布局1.高度 = "auto"
' ② 遍历并调整子组件
变量循环(i = 0,子组件数量,1)
    变量 子组件对象 = 绝对布局1.取子组件(i)
    子组件对象.定位 = ""
    子组件对象.移动("","","","")
    ' ...
结束循环
' ③ 转换布局
绝对布局1.转为弹性布局("column")
' ④ 添加到目标容器
垂直滚动框1.添加组件(绝对布局1)

「组件迁移」的本质是:把一个容器整体挂到另一个容器下。迁移前需调整定位策略(从绝对改为 relative/弹性),否则原绝对布局的子组件无法在新容器中正确排列。

7. 闭包中的循环变量

变量循环(i = 0,10,1)
    变量 局_按钮对象 = 创建 按钮()
    局_按钮对象.置被单击回调((源对象,事件源)=>{
        标签1.文本 = "垂直滚动框中按钮被单击,索引:" + i
    })
结束循环
  • 回调内引用了循环变量 i,依赖拉姆达表达式对当前值的捕获
  • 官方示例普遍采用这种写法,说明轻语言的拉姆达对循环变量按每次迭代的值捕获(类似 JavaScript let 语义)
  • 生成代码时可参照此模式,但若遇异常应改用参数绑定方式

注意事项

  • 循环边界语义:轻语言 变量循环(初始 = 起始, 目标, 递增) 等效于 for(初始=起始; 初始<目标; 初始+=递增),即初始变量小于目标值时循环、达到目标值时退出,左闭右开区间 [起始, 目标)。本演示中 变量循环(i = 0, 子组件数量, 1) 会循环 子组件数量 次(i=0~子组件数量-1),配合 取子组件(i) 遍历子组件正好不越界,是正确的写法。
  • 转为弹性布局 的位置:本演示将其放在循环内,每次迭代都调用一次。功能上因幂等不会出错,但建议放在循环外仅调用一次。
  • 动态组件命名:动态创建的组件不能与 .spldg 中已声明的组件同名,否则会覆盖原有引用。
  • 非绝对布局容器中的子组件:添加到弹性布局、滚动框等容器前,必须设置子组件 定位 = "",否则保留绝对定位会导致布局错乱。
  • 移动 参数类型:带单位的值(如 "50%""60px")必须用双引号包裹为文本;纯整数默认为 px。
  • 类属 运算符:用于判断对象是否为某类型,等价于 instanceof。遍历容器子组件访问子类特有属性前应先做类型判断。
  • 组件迁移本质:是把容器整体挂到另一容器下,迁移前需调整定位策略(绝对 → relative/弹性),否则子组件在新容器中无法正确排列。

学习要点总结

知识点关键代码适用场景
动态创建组件变量 局_按钮 = 创建 按钮()运行时按需生成组件
添加到容器容器.添加组件(组件)动态组件挂载
移动方法移动(10,20,"50%","60px")一次性设置位置尺寸
整数与单位文本10 vs "60px"参数类型选择
清空定位定位 = ""子组件交由父布局
子组件遍历取子组件数() + 取子组件(i)容器内组件处理
类型判断对象 类属 单行输入框子类特有属性访问前判断
转弹性布局转为弹性布局("column")绝对布局转纵向弹性
组件迁移改定位 + 调子组件 + 添加到新容器跨容器移动
闭包回调置被单击回调((源对象,事件源)=>{...})动态组件事件绑定
奇偶特判i % 2 == 0循环中差异化样式

相关文档

  • 文档框架基础类_页面 —— 页面级事件
  • 文档框架基础类_视图 —— 通用方法(移动、定位、置被单击回调等)
  • 文档框架基础类_容器视图 —— 容器通用方法(添加组件、取子组件数、取子组件)
  • 文档布局类组件_绝对布局 —— 绝对布局与 转为弹性布局 方法
  • 文档布局类组件_弹性布局 —— 弹性布局的属性与方向
  • 文档列表类组件_垂直滚动框 —— 垂直滚动框的添加组件方法
  • 文档文本类组件_按钮 —— 按钮的属性与事件
  • 文档文本类组件_单行输入框 —— 单行输入框(类型判断目标)
  • 文档选择类组件_单选框 —— 单选框
  • 文档选择类组件_多选框 —— 多选框
  • 文档轻语言网站:循环语句体结构 —— 变量循环计次循环判断循环 的完整说明
  • 文档轻语言网站:轻语言语法速查 —— 关键字、运算符、拉姆达表达式
  • 文档综合演示:网页留言板开发 —— 列表框数据驱动渲染(另一种动态生成模式)
  • 文档综合演示:手机移动端记事本网页开发 —— 列表项动态创建标签
  • 文档轻语言网站:自定义设计列表内容 —— 列表框/宫格框自定义渲染
  • 文档综合演示:MySQL数据库操作 —— 同样使用 取子组件数 遍历子组件