文档

5. 数据展示和修改

更新时间:

文本介绍如何进行字段数据的展示和修改。

系统组件展示和修改数据

目前我们的组件还没有使用平台的数据,在此之前,我们先以系统组件为例,看下系统组件如何展示和修改数据。

首先我们创建一个实体来表示业务数据。姓名字段是我们要展示和修改的数据。

image.png

然后搭建相关的页面进行展示和修改。

image.png

这里用到三个系统组件:

  1. Data 组件通过上下文数据源加载数据(Data 绑定上下文数据源,若没有上下文对象传递,会自动创建该对象。)。image.png

  2. 文本组件展示字段。image.png

  3. 输入框组件修改字段。image.png

最后我们看下实际运行的效果。

image.png

在输入框内输入内容,上面的文本组件也会跟着改变。

Data 组件加载实体对象,文本组件展示实体对象字段,输入框组件展示和修改数据实体字段。

另外基于平台的数据驱动能力,当字段发生改变时,对应的组件会重新渲染,展示新的数据。

添加组件展示和修改数据能力

接下来,我们在自定义组件上添加数据展示和修改能力。

  1. 在 src/config.ts 中添加属性配置。

    import { API_VERSION, Category } from './api';
    
    export default {
      apiVersion: API_VERSION,
      version: '1.0',
      isContainer: false,
      title: '',
      componentName: 'MobiPcComponentABC',
      category: Category.COMMON,
      icon: 'https://img.alicdn.com/imgextra/i1/O1CN01oufFHB266LbYRkVr3_!!6000000007612-55-tps-20-20.svg',
      configure: [
        {
          title: '数据相关的Prop设置',
          type: 'group',
          display: 'block',
          items: [
            {
              name: 'aAttr',
              title: '选择展示的字段',
              setter: {
                type: 'data-bind-field',
                props: {
                  supportFieldType: ['TEXT', 'CHAR'],
                }
              },
            },
          ],
        },
      ],
    };
    

    字段对应的属性设置器是data-bind-field

  2. 在组件中添加 Props 参数和处理代码。

    import React from 'react';
    import { AttrMeta, PropsWithPageContext } from './api';
    import config from './config';
    import './index.scss';
    
    interface Props {
      aAttr: AttrMeta;
    }
    
    const MobiPcComponentABC = (props: PropsWithPageContext<Props>) => {
      const attrValue = props.pageContext.getAttrValue<string>(props.aAttr);
      return (
        <div className="MobiPcComponentABC">
          <div>{`Hello MobiPcComponentABC ~`}</div>
          <div>{`字段名称 : ${props.aAttr?.name}, 字段类型 : ${
            props.aAttr?.type
          } 字段数值 : ${attrValue.get()} `}</div>
          <input
            value={attrValue.get()}
            onChange={(e) => {
              attrValue.set(e.target.value);
            }}
          />
        </div>
      );
    };
    
    MobiPcComponentABC.config = config;
    
    export default MobiPcComponentABC;
    

    这里有几点需要说明:

    1. data-bind-field 属性设置器配置的 Props 参数类型是AttrMeta,表示平台用户具体设置的实体字段信息,根据 data-bind-field 属性设置器配置的参数不同,还有可能是联合类型,具体请查看data-bind-field

    2. 获取、更新字段数据是调用getAttrValue API,参数就是AttrMeta

    3. getAttrValue API 挂载在平台向组件 Props 注入的 API 接口 PageContext 上。

    4. PropsWithPageContext 是方便组件开发者定义 Props 的辅助类型,参见 PropsWithPageContext

  3. 组件设计时加载效果如下,我们配置上对应字段:image.png

  4. 组件运行时加载效果如下:image.png可以看到组件正确的展示了字段数据,而且输入框组件修改字段,自定义组件也会更新,自定义组件修改字段,文本、输入框组件都会更新。

设计时和运行时区分

在上面修改自定义组件的过程中,我们可以看到,设计时(应用搭建时)并不会有数据存在。

为了提高组件使用方的体验,我们可以区分设计时、运行时(应用真正运行时)展示不同的效果。

比如文本组件和输入框组件,设计时展示的是 {姓名},运行时展示的是姓名字段的值。

image.png

平台提供了一些 API 来支持实现这些效果:

  1. isPreview 判断是否是运行时。

  2. formatForDesignTips 统一包装要展示的字符串,添加{}。

说明

组件是否区分设计时和运行时,由组件开发者自己决定,平台不会有强制要求。

实现思路总结

和事件响应类似,数据展示和修改也是基于属性设置,设置的 Props 参数本身并不是数据,而是实体字段的定义,具体的数据需要通过 API 获取,修改也是通过 API 修改。

总结来说步骤如下:

  1. 添加一个属性,使用data-bind-field,使用户可以配置要操作的实体字段。

  2. 添加对应的 Props 参数,类型为AttrMeta

  3. 在组件渲染时,通过getAttrValue API 获取数据的获取和更新接口,渲染数据。

    1. 可以考虑区分设计时和运行时的渲染内容,提高用户体验。

  4. 在组件触发数据变化的回调方法中,调用更新接口,更新数据。

与 React 组件的区别

一般处理数据的 React 组件,都会有两个 Props 参数,一个用于传递数据,一个用于响应数据变化。如下:

import React from 'react';

interface Props {
  value: string;
  onChange: (value: string) => void;
}

const ComponentA = (props: Props) => {
  const { value, onChange } = props;
  return (
    <div>
      <input value={value} onChange={(e) => onChange(e.target.value)} />
    </div>
  );
};

value:要展示的数据

onChange:数据变化时的回调方法,新数据以参数的形式返回。

主要区别如下:

  1. 平台组件的 Props 参数只需要一个,含义是实体字段模型,并不是数据本身。相应数据的获取,就需要调用 API 来获取

  2. 数据更新时,不需要通过 Props 回调参数反馈给应用,而是通过调用 API 更新数据。

数据驱动

在上面的例子中,当实体字段发生改变后,使用字段的组件会自动重新渲染,这是平台提供的一种数据驱动能力。

在开发自定义组件时,要充分的利用数据驱动能力,有一些限制需要注意:

  1. 字段数据必须在render方法内读取。反之,如果render方法执行过程中没有读取字段数据,当此字段更新时,组件是不会因为数据驱动触发render的。

  2. 字段数据的读取必须是在最外层的组件内读取, 举例如下:

    import React from 'react';
    import { AttrMeta, PageContext, PropsWithPageContext } from './api';
    
    interface PropsB {
      aAttr: AttrMeta;
      pageContext: PageContext;
    }
    
    const ComponentB = (props: PropsB) => {
      return <div>{props.pageContext.getAttrValue<string>(props.aAttr).get()}</div>;
    };
    
    interface PropsA {
      aAttr: AttrMeta;
    }
    
    const ComponentA = (props: PropsWithPageContext<PropsA>) => {
      return <ComponentB aAttr={props.aAttr} pageContext={props.pageContext} />;
    };
    export default ComponentA;
    

    假设 ComponentA 是直接暴露给平台的组件,而 ComponentB 是 ComponentA 内部定义的其它组件,字段类型是CHAR。

    这里把 aAttr 和 pageContext 传递给 ComponentB,由 ComponentB 来读取字段数据。

    在这种情况下,当字段发生变化时,并不会触发 ComponentA 和 ComponentB 的重新渲染。

    如果要支持数据驱动,需要做如下改动:

    import React from 'react';
    import { AttrMeta, PropsWithPageContext } from './api';
    
    interface PropsB {
      value: string;
    }
    
    const ComponentB = (props: PropsB) => {
      return <div>{props.value}</div>;
    };
    
    interface PropsA {
      aAttr: AttrMeta;
    }
    
    const ComponentA = (props: PropsWithPageContext<PropsA>) => {
      return <ComponentB value={props.pageContext.getAttrValue<string>(props.aAttr).get()} />;
    };
    export default ComponentA;

    把字段数据的读取放到 ComponentA 内,直接传递数据给 ComponentB 使用。这样字段发生变化时,ComponentA 会重新渲染,从而使 ComponentB 也重新渲染。

静态数据和动态数据

有一些场景,组件需要的数据并不一定是实体对象的字段。

比如文本组件,展示的文本内容可以是平台用户在搭建时设置的静态字符串,也可以是实体对象的字段,甚至是模板字符串。

image.png

平台为这种场景提供了以下支持:

  1. data-bind-field通过修改配置的参数,可以实现由用户选择数据类型。对应的 Props 参数也会变成联合类型。比如可以是静态字符串,也可以是实体字段,Props 参数的类型就会变成 AttrMeta | string 这种类型。

  2. getAttrValue API 兼容静态数据和模板字符串这两种场景。如果用户设置的是静态字符串或者模板字符串,相应的更新接口就会是空实现(因为静态字符串和模板字符串不能修改)。

    1. data-bind-field 属性设置器是支持配置允许设置的字段类型的,所以对于限制了类型的字段,可以类似 getAttrValue<string> 或者 getAttrValue<boolean> 这样获取确定的结果。

字段类型定义

在创建实体模型时,实体字段有对应的字段类型(参考新增字段的说明),在组件代码中,对应关系如下

字段类型

对应代码定义

备注

INTEGER

LONG

DECIMAL

number

JS的基础类型

BOOLEAN

boolean

JS的基础类型

CHAR

TEXT

string

JS的基础类型

DATETIME

Date

JS的标准内置对象

ENUMERATION

EnumValue

平台API定义的对象EnumValue

FILE

IMAGE

AUDIO

VIDEO

DOCUMENT

FileValue

平台API定义的对象FileValue

接下来

掌握了组件如何展示和修改数据后,让我们看下6. 开发容器组件,学习让组件变成容器组件。

  • 本页导读
文档反馈