组件模版

组件模板是 .gen 文件中的核心部分,用于描述页面结构。它包含在 <template> 标签中,语法风格类似 HTML,但结合了组件系统的增强语法。

基本语法

组件的声明方式分为两种:常规标签自闭合标签

常规标签

  • 由一对 <$component_name></$component_name> 包裹
  • 支持设置组件属性、绑定值、事件回调
  • 支持嵌套子组件

自闭合标签

  • 形式为 <$component_name />
  • 不允许有子组件
  • 同样支持设置属性、绑定和事件

语法示例

1<template>
2    <$component_name
3        $($($static_prop="$prop_value")*)?
4        $($(:$bind_prop="$bind_ident")*)?
5        $($(@callback="$callback_ident($($arg),*)")*)?
6    >
7        <$component_name
8            $($($static_prop="$prop_value")*)?
9            $($(:$bind_prop="$bind_ident")*)?
10            $($(@callback="$callback_ident($($arg),*)")*)?
11        />
12        // ...
13    </$component_name>
14</template>
  • $component_name: 组件名称
  • $static_prop: 静态属性
  • $prop_value: 属性值
  • $bind_prop: 绑定属性
  • $bind_ident: 绑定变量标识符
  • $callback: 回调
  • $callback_ident: 回调方法标识符
  • $arg: 参数
  • $()*: many1,1 个或多个
  • $()?: recognize,0 个或 1 个

示例

root.gen
1<template>
2  <view id="UiRoot">
3    <label text="'Hello GenUI!'"></label>
4    <view height="100.0" width="100.0" theme="Info"></view>
5    <tag text="'hello'" />
6  </view>
7</template>

语法规则

在语法规则部分我们会详细讲述组件模版的编写规则

根组件

根组件指的是每个.gen文件中组件模版部分的根组件,即<template>标签包裹的首个标签

1<template>
2  <view id="UiRoot"></view>
3</template>

在这个例子中根组件就是<view id="UiRoot"></view>

唯一根原则

任何组件模版有且只有一个唯一的根组件,且根组件必须有一个唯一名称

静态唯一根
动态唯一根
1<view id="SpecialName"></view>
TIP

您可能发现了静态和动态使用的唯一命名属性是不同的,静态使用id动态使用name

它们之间的区别在于,使用静态唯一根时您无法进行任何脚本级代码操作,即使用<script>

命名引用原则

  1. 该原则只对根组件生效,对根组件而言,唯一名称就是外部引用时的组件名,例如当唯一名称为Hello时,在其他组件中使用<Hello></Hello>表示该组件
  2. 您也可以使用snake name rule进行根组件的命名,例如: my_view1,但在其他组件中引入时依然会转为camel name rule,即:<MyView1></MyView1>
  3. 命名引用原则只对外部引用有效

默认继承原则

对于根组件,默认继承view视图组件,不可更改,我们希望每个被封装的组件都可以作为独立的单个视图出现。

内外原则

上方对于根组件idname的说明我们称为对内原则和对外原则,id对内,name对外,意思是:

  • id仅对当前被封装的组件内部起效,外部无法通过内部的id获取内部组件
  • name仅对外有效,是外部使用被封装组件的途径,对内无法用name对组件进行获取,且name只存在于<component>

静态属性

静态属性的写法为:$static_prop="$prop_value",多个属性由空格分割,例如:

1<view height="100.0" width="200.0"></view>

组件的属性值是有类型的,错误类型无法编译通过

TIP

属性值的类型请参考: 数据类型

id

id是组件的唯一标识,每个组件都有这个属性,通过id可以获取到对应的组件,同时它也是组件的属性标识

1<label id="my_label"></label>
TIP

如果您无法理解,请先阅读内外原则

class

class是组件的属性(样式)标识,通过class可以将样式(<style>)部分对于的样式合并到组件中

  • class没有唯一性
  • 一个组件可以有多个class,但不能声明多个class
1<label class="common_label"></label>
2
3<label class="[common_label, bold_label, font_smaller]"></label>

as_prop属性组件

as_prop属性会把某个组件转为其父组件的属性,源自于Makepad中构建插槽的一种方式

目前在button, view, popup 等组件中涉及

绑定属性 (自动双向绑定)

对于需要绑定的属性使用:作为属性的前缀,在模版中使用绑定属性的前提是在<script>中的根组件声明中对绑定的属性进行声明,写法如下:

1<view id="my_view" :height="view_h"></view>

计算属性

计算属性(Computed Property)是基于现有属性动态计算出的值,在 GenUI 中,计算属性不会存储状态,而是根据其依赖项的变化自动更新。

特性计算属性 (Computed)双向绑定 (Two-way Binding)
是否存储状态❌ 否✅ 是
是否可变✅ 依赖项变化时更新✅ 是
是否可手动修改✅ 但不能使用 set_xxx 方法✅ 通过 set_xxx 修改
依赖数据✅ 需要依赖项✅ 组件状态

计算属性的写法为在属性绑定时使用方法进行声明:

1<view id="my_view" :height="view_h()"></view>
TIP

对计算属性的详细说明见 Api: #[computed]

回调

回调表示组件激发某个事件之后调用的某个方法,使用@作为回调前缀,写法如下:

1<button id="my_btn" @clicked="click_btn()"></button>
TIP

回调中可能没有任何参数,但依然需要添加()

若组件使用了回调一定要添加id作为标识符

自动 ID 策略

v0.1.2 起,GenUI 引入了自动 ID 分配策略。在组件构建过程中,系统会自动检查每个组件是否已显式指定 id,若未指定,则会为其生成一个随机的唯一 ID。

这一机制在多个场景下都极为有用,包括:

  • 属性绑定(:prop="..."
  • 事件回调(@event="..."
  • 计算属性关联
  • 各类语法糖处理

自动 ID 的引入极大地减少了手动管理标识符的繁琐,提高了模板代码的简洁性和可维护性。

ID 生成规则

我们并未采用 ulid 或其他第三方库,而是根据以下自定义策略生成 ID:

  1. 以英文字母开头:确保符合变量命名规范,避免潜在语法冲突。
  2. 长度限制:ID 长度控制在 6 ~ 12 个字符之间,避免过短冲突或过长冗余。
  3. 字符组成:仅包含英文字母与数字,不含特殊字符,以保持兼容性和可读性。