综合演示: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 ← 页面逻辑文件(轻语言代码,动态创建与迁移)
运行时流程如下:
- 浏览器加载
demo页面 → 框架解析demo.spldg构建静态 DOM(根布局、标签1、垂直滚动框1、按钮1、绝对布局1 及其 3 个子组件) - 执行
demo.spl中的页面加载完毕事件:- 动态创建 1 个按钮 → 设置文本、位置、单击回调 → 添加到
根布局 - 调用
动态批量创建组件()→ 在垂直滚动框1中循环创建多个按钮
- 动态创建 1 个按钮 → 设置文本、位置、单击回调 → 添加到
- 用户点击「按钮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数据库操作—— 同样使用取子组件数遍历子组件