前端视图的元数据与数据的传递、交互

在阅读本篇文章之前,您需要学习以下知识点:

1: 元数据

视图的元数据

在日常开发中,我们会经常遇到自定义的字段、动作、视图需要界面设计器配置的数据,这些数据可能是当前页面的字段,也有可能动作,那么如何获取呢?

视图元数据分为两种:
1: 当前视图(metadataRuntimeContext)
2: 根视图(rootRuntimeContext)

那么这两种类型怎么区分呢?

举个例子:
1: 如果当前字段是在表单中,那么当前视图就是表单,根视图就表单的父级视图,如果只有一个表单视图,那么当前视图就是根视图。
2: 如果当前视图是表单,但是表单里面有个表格,对于表格字段而言,当前视图就是表格,根视图就是表单。

当前视图的元数据(metadataRuntimeContext)

在前端,我们通过 metadataRuntimeContext 来获取视图的元数据,例如:

export class CustomFormStringFieldSingleWidget extends FormStringFieldSingleWidget {
  protected mounted(): void {
    console.log(this.metadataRuntimeContext);
  }

    /**
  * 界面设计器配置的动作
  */
  @Widget.Reactive()
  protected get modelActions() {
    return this.metadataRuntimeContext.model.modelActions
  }

   /**
  * 界面设计器配置的字段
  */
  @Widget.Reactive()
  protected get modelFields() {
    return this.metadataRuntimeContext.model.modelFields
  }
}
属性名 类型 可选性 描述
viewAction RuntimeViewAction 运行时跳转动作(通过跳转动作创建的运行时上下文具备该属性)
module RuntimeModule 运行时模块
model RuntimeModel 运行时模型
view RuntimeView 运行时视图
viewLayout DslDefinition \| undefined 视图布局 DSL,从运行时视图解析获得
viewDsl DslDefinition \| undefined 视图模板 DSL,从运行时视图解析获得
viewTemplate DslDefinition 视图最终执行 DSL,从运行时视图解析获得或根据布局 DSL 和模板 DSL 合并生成
getModel (model: string, isBelong?: boolean) => GetModelResult \| undefined 获取模型,返回获取的模型和所在的运行时上下文
getModelField (data: string, isBelong?: boolean) => GetModelFieldResult \| undefined 获取模型字段,返回获取的模型字段和所在的运行时上下文
getRequestModelFields (options?: GetRequestModelFieldsOptions) => RequestModelField[] 获取请求字段
getDefaultValue () => Promise<Record<string, unknown>> 获取默认值
getInitialValue () => Promise<Record<string, unknown>> 获取初始值

运行时模型(model)

属性名 类型 可选性 描述
id string 模型 id
model string 模型编码
name string 技术名称
modelFields RuntimeModelField[] 模型字段
modelActions RuntimeAction[] 模型动作
type ModelType 模型类型
module string 模块编码
moduleName string 模块名称
moduleDefinition RuntimeModule 模块定义
pks string[] 主键
uniques string[][] 唯一键
indexes string[][] 索引
sorting string 排序
label string 显示标题
labelFields string[] 标题字段

可通过modelFieldsmodelActions获取界面设计器配置的模型字段、模型动作。

当前视图的 dsl(viewDsl)

视图的 DSL,从运行时视图解析获得,如果模型中的modelFieldsmodelActions获取不到的对应的字段、动作,那么可从该属性中获取

默认值(getDefaultValue)

用来获字段的默认值(界面配置器配置的)

根视图的元数据(rootRuntimeContext)

根视图的元数据结构跟当前视图的元数据类似。

视图数据

视图数据是贯穿于应用程序前端和视图层的关键数据,它承载了应用逻辑到用户界面之间的桥梁作用。

在 oinone 前端中,常见的视图数据分为如下几种:

1: 表单数据(formData)
2: 列表数据(dataSource)
3: 根视图数据(rootData)
4: 当前字段、动作所在的区域数据(activeRecords)
5: 按钮打开弹窗、抽屉的时候,按钮所在的区域数据(openerActiveRecords)

formData

formData 是一个对象,对象中的每个属性对应一个表单项,表单项的值就是该属性的值。所有的表单字段都可以通过this.formData来访问,也可以通过this.formData.xxx来获取某个字段的值。

dataSource

dataSource 是一个数组,数组中的每个元素对应一个列表项,列表项的值就是该元素。所有的列表字段都可以通过this.dataSource来访问,也可以通过this.dataSource[0].xxx来获取某个列表字段的值。

rootData

rootData 是一个数组,如果当前视图是列表,那么 rootData 是列表的数据源。如果当前视图是表单,那么 rootData 是表单的数据源,其中的第 0 项是当前表单的数据。

activeRecords

activeRecords 是一个数组

1: 表单视图的动作
    1.1: activeRecords 是表单的数据源,其中的第 0 项是当前表单的数据。
2: 表格视图上方的动作
    2.1: activeRecords 是当前选中的行数据,其中的第 0 项是对应的数据。
3: 表格的行内动作
    3.1: activeRecords 是当前行数据,其中的第 0 项是对应的数据。

openerActiveRecords

openerActiveRecords 是一个数组,用于保存当前页面的 opener 页面选中的数据。

1: 比如 行内动作 点击打开弹窗,弹窗里面的字段或者动作可以通过 openerActiveRecords 获取 行内 数据.
2: 比如 表单中的动作 点击打开弹窗,弹窗里面的字段或者动作可以通过 openerActiveRecords 表单 数据.

特殊数据

activeTreeContext 树组件的选中数据

activeTreeContext 树组件的选中数据,可以获取到选中的数据,以及选中的数据的父级数据,用于左树右表的视图.

常见场景:

场景 1: 左树右表的视图,表格上方的创建按钮点击打开弹窗弹窗里面要获取左树选中的数据,用于创建数据.
方案:点击弹窗里面的创建按钮时,通过 this.metadataRuntimeContext.view?.activeTreeContext 获取到左树选中的数据

class CustomActon extends ServerActionWidget {
  protected async executeAction(action: RuntimeServerAction, submitValue: SubmitValue){
    const treeContext = this.metadataRuntimeContext.view?.activeTreeContext || {}
    submitValue.records = {
      ...submitValue.records,
      ...treeContext
    }
    super.executeAction(action, submitValue)
  }
}

场景 2: 左树右表的视图,表格上方的创建按钮点击打开新页面新页面里面要获取左树选中的数据,用于创建数据.
方案:点击新页面里面的创建按钮时,可通过URL参数获取到左树选中的数据

class CustomActon extends ServerActionWidget {
  protected async executeAction(action: RuntimeServerAction, submitValue: SubmitValue){
    const treeContext = JSON.parse(this.getUrlParameters().context).activeTreeContext || {}
    submitValue.records = {
      ...submitValue.records,
      ...treeContext
    }
    super.executeAction(action, submitValue)
  }
}

searchBody 搜索条件、searchConditions 固定查询条件

参考文章

Oinone社区 作者:汤乾华原创文章,如若转载,请注明出处:https://doc.oinone.top/frontend/18209.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
汤乾华's avatar汤乾华数式员工
Previous 2024年10月8日 am10:37
Next 2024年10月8日 pm5:55

相关推荐

  • 上下文在字段和动作中的应用

    上下文在字段和动作中的应用 在业务场景中,常常需要在打开弹窗或跳转到新页面时携带当前页面数据。此时,我们需要配置相关「动作」中的上下文信息。 在 oinone 平台中,上下文主要分为以下三种: activeRecord:当前视图数据 rootRecord:主视图数据 openerRecord:触发弹窗的对象 参考文档:oinone内的主视图数据和当前视图数据使用介绍 activeRecord 表示当前视图的数据。例如,若动作配置在表单上,则指代当前表单的数据;若配置在 o2m、m2m 字段表格上,则指代选中的行数据。 rootRecord 表示根视图的数据。若当前视图是表单页,则代表表单的数据;若为表格页,则代表表格的数据。 openerRecord 表示触发弹窗的对象。例如,在弹窗内的字段或动作中,可通过 openerRecord 获取触发弹窗的信息。 这三者均为对象 (Object) 类型。 界面设计器配置 在 o2m、m2m 表格字段弹窗中携带当前视图数据 假设我们设计了一个包含 o2m、m2m 表格字段的表单页面。打开相关弹窗时,需将表单中的 code 数据传递至弹窗中。 选择相应的「动作」,如创建或添加。在右侧属性面板底部找到「上下文」,添加格式为对象 {} 的上下文信息。 以键值对的格式添加上下文信息:{code: rootRecord.code}。 设计弹窗时,将 code 字段拖入弹窗中。 完成设计后保存并发布。 大家可以看到,上下文中的key是 code,但是value是rootRecord.code,这里取的是rootRecord而不是activeRecord,因为我们上面讲过如果当前动作配置在o2m、m2m的字段表格上面,那么activeRecord就是表格选中的行,我们现在要取的是表单上的code字段,所以需要用rootRecord。 注意点:key需要是提交模型【前端视图】存在的字段才能传递。

    2023年11月8日
    3.2K10
  • 如何编写自定义字段组件的校验逻辑

    介绍 自定义字段组件的时候,我们可能会遇到有复杂校验规则或者业务上特殊的校验提示信息的场景,这时候可以通过覆写字段的校验方法validator来实现。 示例代码 import { SPI, ValidatorInfo, FormStringFieldWidget, isEmptyValue, isValidatorSuccess, FormFieldWidget, ViewType, ModelFieldType } from '@kunlun/dependencies' @SPI.ClassFactory(FormFieldWidget.Token({ viewType: [ViewType.Form], ttype: ModelFieldType.String, widget: 'DemoPhone' })) export class DemoFormPhoneFieldWidget extends FormStringFieldWidget { // 字段校验方法 public async validator(): Promise<ValidatorInfo> { // 建议先调用平台内置的通用校验逻辑 const res = await super.validator(); if (!isValidatorSuccess(res)) { // 校验失败直接返回 return res; } // 编写自有校验逻辑 if (!isEmptyValue(this.value) && !/^1[3456789]\d{9}$/.test(this.value as string)) { // 通过内置的validatorError方法提示校验提示信息 return this.validatorError('手机号格式错误'); } // 无异常,用内置的validatorSuccess返回校验通过的信息 return this.validatorSuccess(); } } 扩展学习 自定义字段组件如何处理vue组件内的表单校验

    2024年8月23日
    2.3K00
  • 【路由】浏览器地址栏url参数介绍

    介绍 浏览器地址栏url为路由类型的视图动作(viewAction)的访问url 详情页示例url https://one.oinone.top/page;module=resource;viewType=DETAIL;model=resource.ResourceDistrict;action=redirectDetailPage;scene=redirectDetailPage;target=ROUTER;menu=%7B%22selectedKeys%22:%5B%22%E5%8C%BA%22%5D,%22openKeys%22:%5B%22%E5%9C%B0%E5%9D%80%E5%BA%93%22,%22%E5%9C%B0%E5%8C%BA%22%5D%7D;id=575733837679260950;path=%2Fresource%2F%E5%8C%BA%2FACTION%23resource.ResourceDistrict%23redirectDetailPage 通过调试工具查看解析后的信息 参数介绍 module 动作所在模块名称 viewType 视图类型 model 动作所在模型的编码 action 动作名称 target 动作打开方式,ROUTER为当前路由打开,OPEN_WINDOW为新窗口打开 menu 【选填】菜单栏控制参数,该参数不影响页面的业务逻辑,仅影响菜单栏展开哪些菜单项(通过openKeys属性),选中哪些菜单项(通过selectedKeys属性)),该参数经过JSON.stringify(menu)方式处理过 # 示例参数 { "selectedKeys": ["区"], "openKeys": ["地址库", "地区"] } id 【选填】详情、编辑等单行数据页面的数据id searchBody 列表页搜索区域的搜索条件,该参数在前端经过encodeURIComponent(JSON.stringify(searchBody))方式处理过 # 示例参数 { "code": "11" } searchConditions 列表页高级搜索条件,用于处理searchBody之外的复杂搜索条件,日常开发中无需关心该参数encodeURIComponent(JSON.stringify(searchConditions))方式处理过 # 示例参数 [ { "leftValue":["sourceType"], "operator":"==", "right":"GD" } ] context 上下文参数,该参数经过JSON.stringify(menu)方式处理过 列表页的此参数会填充到搜索区域的字段中作为默认的查询条件,详情 详情页和表单页此参数会作为页面加载函数的入参 # 示例参数 { “cateId”: “61723712399821” } path 权限验证路径,父页面编译的时候自动加上该参数,在父页面点击当前动作的时候会自动拼该参数 scene 【选填】动作场景值 代码中如何获取 这里介绍在组件内如何获取 import { BaseElementWidget } from ‘@kunlun/dependencies’; export class DemoElementWidget extends BaseElementWidget { protected test() { const { module, model, action } = this.urlParameters; } } 推荐阅读相关文档 上下文在字段和动作中的应用 如何实现页面间的跳转

    2024年8月19日
    4.3K00
  • 【前端】默认布局模板(v4)

    默认母版(Mask) PC端默认母版 <mask> <multi-tabs /> <header> <widget widget="app-switcher" /> <block> <widget widget="notification" /> <widget widget="divider" /> <widget widget="language" /> <widget widget="divider" /> <widget widget="user" /> </block> </header> <container> <sidebar> <widget widget="nav-menu" height="100%" /> </sidebar> <content> <breadcrumb /> <block width="100%"> <widget width="100%" widget="main-view" /> </block> </content> </container> </mask> PC端默认内联Tabs母版(<multi-tabs inline="true" />) <mask> <header> <widget widget="app-switcher" /> <block> <widget widget="notification" /> <widget widget="divider" /> <widget widget="language" /> <widget widget="divider" /> <widget widget="user" /> </block> </header> <container> <sidebar> <widget widget="nav-menu" height="100%" /> </sidebar> <block height="100%" flex="1 0 0" flexDirection="column" alignContent="flex-start" flexWrap="nowrap" overflow="hidden"> <multi-tabs inline="true" /> <content> <breadcrumb /> <block width="100%"> <widget width="100%" widget="main-view" /> </block> </content> </block> </container> </mask> 移动端默认母版 <mask> <widget widget="user" /> <widget widget="nav-menu" app-switcher="true" menu="true" /> <widget widget="main-view" height="100%" /> </mask> PC端默认布局(Layout) 表格视图(TABLE) <view type="TABLE"> <pack widget="group"> <view type="SEARCH"> <element widget="search" slot="search" /> </view> </pack> <pack widget="group" slot="tableGroup"> <element widget="actionBar" slot="actionBar"> <xslot name="actions" /> </element> <element widget="table" slot="table"> <element widget="expandColumn" slot="expandRow" /> <xslot name="fields" /> <element widget="rowActions" slot="rowActions" /> </element> </pack> </view> 表单视图(FORM) <view type="FORM"> <element widget="actionBar" slot="actionBar"> <xslot name="actions" /> </element> <element widget="form" slot="form"> <xslot name="fields" /> </element> </view>…

    2023年11月1日
    1.6K01
  • 如果让表单支持单选 ?

    本文将介绍在代码和XML配置中的修改,支持表格的单选功能。 先自定义一个widget,继承平台默认的table @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Table, widget: 'MyRadioTable' }) ) export class MyRadioTable extends TableWidget { @Widget.Reactive() protected get selectMode(): ListSelectMode { return ListSelectMode.radio; } } 注册layout 如果当前是主表格,那么xml配置如下 const xml = `<view type="TABLE"> <pack widget="group"> <view type="SEARCH"> <element widget="search" slot="search" slotSupport="field" /> </view> </pack> <pack widget="group" slot="tableGroup"> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <element widget="MyRadioTable" slot="table" slotSupport="field"> <element widget="expandColumn" slot="expandRow" /> <element widget="RadioColumn" /> <xslot name="fields" slotSupport="field" /> <element widget="rowActions" slot="rowActions" slotSupport="action" /> </element> </pack> </view>` registerLayout(xml, { moduleName: '模块名称', model: '模型', viewType: ViewType.Table }) 如果当前的表格是form表单页面的表格,那么xml配置如下 const xml = `<view type="TABLE"> <view type="SEARCH"> <element widget="search" slot="search" slotSupport="field" /> </view> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <element widget="MyRadioTable" slot="table"> <element widget="expandColumn" slot="expandRow" /> <element widget="RadioColumn" /> <xslot name="fields" slotSupport="field" /> <element widget="rowActions" slot="rowActions" /> </element> </view>` registerLayout(xml, { moduleName: '模块名称', model: '模型', viewType: ViewType.Table })

    2023年11月27日
    1.1K00

Leave a Reply

Please Login to Comment