跳到主要内容

XDSL

提示
  • Nop 平台还处于开发阶段, 本文档中的实践方案可能会部分失效,但本人精力有限,无法及时跟进,请自行按照最新代码调整;
  • 您可以与 DeepWiki 进行问答互动(支持中文)以深入学习 Nop 平台的设计与实现;
  • 若此文对您有很大帮助,请投币支持一下吧;
版权声明

对 XDSL 结构的定义见 /nop/schema/xdsl.xdef

定义

示例

属性

x:name

名称类型必填?
x:name

string

x:key-attr

名称类型必填?
x:key-attr

xml-name

x:extends

名称类型必填?
x:extends

v-path-list

[仅根节点] 当前 DSL 所要继承的基础模型的 v-path 资源列表(以逗号分隔):

<biz x:extends="/path/to/a.xbiz,/path/to/b.xbiz"
...>
<!-- ... -->
</biz>

除普通的 v-path 资源路径以外,还可以在 x:extends 列表中包含以下标识符:

  • none: 忽略在当前 DSL 的 XDef 中设置的 xdef:default-extends 缺省基础模型, 也就是,不继承缺省的模型,单独指定全新的基础模型,如 x:extends="none,/path/to/default.xui"
  • super: 在 Delta 层中,指定其继承自上一层中的相同路径的 DSL 模型, 从而对上一层的 DSL 做差量更新;

注意:在生成 class 模型时,x:extends 的基础模型 class 与当前模型的 class 没有继承关系,对于二者相同的结构,也是各自单独生成,互不影响。

x:override

名称类型必填?
x:override

io.nop.xlang.xdef.XDefOverride

x:prototype

名称类型必填?
x:prototype

string

[仅兄弟节点] 兄弟节点之间通过 x:prototype 指定继承关系,从而实现节点之间的复用。 该配置项的值为目标原型节点的唯一 id(由 xdef:key-attr 或者 xdef:unique-attr 指定的唯一属性)的值。

若是在 XDef 中为节点配置了 xdef:body-typemap,则其子节点间可通过标签名指定 x:prototype 继承关系。

注意x:extends 是针对不同 DSL 文件之间的相同节点(即,定位坐标相同)的扩展,其通过 x:override 指定合并算子。

x:prototype-override

名称类型必填?
x:prototype-override

io.nop.xlang.xdef.XDefOverride

用于指定基于 x:prototype 进行节点合并时所对应的合并算子:

  <button>
<font size="1.5em" />
<border size="1px" style="solid" color="#aaaaaa" />
</button>
<button-red x:prototype="button">
<border x:prototype-override="remove" />
</button-red>

<!-- button-red 的合并结果为 -->
<button-red>
<font size="1.5em" />
</button-red>

假如有如下两个存在 x:extends 扩展关系的 DSL:

button.styles.xui
<styles>
<button>
<size height="4em" />
<font size="1.5em" />
<border size="1px" style="solid" color="#aaaaaa" />
<background color="red" />
</button>

<button-red x:prototype="button">
<margin left="1em" />
<background color="blue" />
<border x:prototype-override="remove" />
</button-red>
</styles>
button-ext.styles.xui
<styles x:extends="button.styles.xui">

<button-red>
<background x:prototype-override="remove" />
<font x:prototype-override="remove" />
<margin x:override="remove" />
</button-red>
</styles>

若是要在 button-ext.styles.xui 中删除 <button-red /> 节点内的子节点,则需要确定子节点是最先定义在 x:prototype 指定的节点上的,还是最先定义在 x:extends 节点上的。

若是前者,则必须使用 x:prototype-override="remove" 才能完全删除目标子节点,若是该子节点在 x:extendsx:prototype 节点上都有定义,则采用 x:override="remove" 将只会删除 x:extends 节点上的定义,但 x:prototype 节点上的定义将会保留下来。比如:

button-ext.styles.xui
<styles x:extends="button.styles.xui">

<button-red>
<background x:override="remove" />
</button-red>
</styles>

将会得到如下合并结果:

button-ext.styles.xui
<styles x:extends="button.styles.xui">

<button-red>
<background color="red" />
...
</button-red>
</styles>

而若是子节点只在 x:extends 节点上有定义,则需要采用 x:override="remove" 才能删除该节点。比如前例中的 <margin x:override="remove" />

节点

x:config

名称类型必须?
x:config

xpl

通过 <c:import/> 导入 Java 常量或 xlib 标签:

button.xui
<component x:schema="component.xdef">
<x:config>
<c:import as="Button" class="io.xui.component.Button"/>
<c:import from="/my/app.xlib"/>
</x:config>
</component>

其只能定义在 DSL 根节点中,并在调用 DslModelParserGenericDslParserparseFromResourceparseFromNodeparseNodeFromResource 等方法时被执行。

被导入的 Java 常量和 xlib 标签可以在 <x:gen-extends/><x:post-extends/><x:post-parse/> 内直接使用:

button.xui
  <x:gen-extends>
<app:CustomTag .../>
</x:gen-extends>

也可以 #{xxx} 形式在 DSL 中支持编译期表达式的属性中引用:

button.xui
  <template>
<native name="#{Button.NAME}" />
</template>

name 属性的类型定义为 #ns-name,即,在类型前加上修饰符 #

注意<x:config/> 中只能包含 <c:import/> 标签。

注意<c:import/> 只有 <c:import as="Xxx" class="x.x.Xxx"/><c:import as="xxx" from="/path/to/xxx.xlib"/> 两种形式,前者导入类,后者导入 xlib 标签库。

附录