choerodon-ui/pro入门 - dataset 的使用

Choerodon UI 介绍

Choerodon UI 是基于 Ant Design@3.4.0 的 React 实现,开发和服务于企业级后台产品。

dataSet 学习

dataSet 就是一个store 可以随意处理

Transport 的使用

dataSet 中的 transport 里面封装了 dataset 与后端交互的一些基本方法,利用 transport 中的方法可以很容易实现数据的增删改查和校验等功能。

方法介绍
  • read - 查询请求的 axios 配置或 url 字符串
  • create - 新建请求的 axios 配置或 url 字符串
  • update - 更新请求的 axios 配置或 url 字符串
  • destroy - 删除请求的 axios 配置或 url 字符串
  • validate - 唯一性校验请求的 axios 配置或 url 字符串
  • submit - create, update, destroy 的默认配置或 url 字符串
基本使用方法
// DetailDS.js - 将 dataSet 单独抽离出来的文件

// 调用getCurrentOrganizationId 可以获取 CurrentOrganizationId
import { getCurrentOrganizationId } from 'utils/utils';    

const API_LIST = '/lightkits';
const organizationId = getCurrentOrganizationId();

export default () => {
  detailDS = new DataSet({
    // 自动查询,开启即进入页面自动调用 transport 中的 read 方法
    autoQuery: true,   
    fields: [  
      {
        name: 'id',
        // 当字段名相同时,ui 组件上则会展示对应的 label 标签,并且数据为通过 read 方法获取到的所对应字段的数据。
        label: '员工ID',  
        // 字段类型,可选值:boolean number string date dateTime time week month year email url intl object
        type: 'number',  
      },
      {
        name: 'employeeName',
        label: '员工姓名',
        type: 'string',
        // 必输字段。如果没有输入,会有默认的必输提示。
        required: true,
      },
      {
        name: 'employeeNumber',
        label: '员工编号',
        type: 'string',
        required: true,
      },
      {
        name: 'hiredate',
        label: '入职时间',
        // 字段类型为日期类型时,组件中对应的输入框会变为日期选择框
        type: 'date',
      },
      {
        name: 'email',
        label: '邮箱',
        // 字段类型为 email 时,组件会校验输入内容是为 email 
        type: 'email',
        required: true,
      },
      {
        name: 'age',
        label: '员工年龄',
        /**
         字段类型为 number 时,组件展示为数字输入框,只能输入数字,
         并且后端对应字段的数据不为number时,就无法展示该数据。
        */
        type: 'number',
        // 步距,当字段类型为 number 时,在设置 step 之后,文本输入框会变为 NumberField。
        step: 1,  
        // 最小值
        min: 1, 
        // 最大值
        max: 100,  
        required: true,
      },
      {
        name: 'enable',
        label: '是否有效',
        // 字段类型为 boolean 时,组件展示为选择框
        type: 'boolean',  
        // true 对应的值,类型:boolean|string|number,默认 true
        trueValue: '1',  
        // false 对应的值,类型:boolean|string|number,默认 false
        falseValue: '0', 
      },
    ],
    transport: {
      read: ({ data, params, dataSet }) => {
        /*
          触发 read 的两种方式:
           1. 通过在 dataSet 中设置自动查询参数 autoQuery: true,这样每次组件渲染的时候就会自动去获取数据。
           2. 通过 dataSet 的 query() 方法手动触发 read 获取数据,即在组件中调用 this.detailDS.query()。
        */
        const url = `${API_LIST}/v1/${organizationId}/headers/getHeaderList`;
        const axiosConfig = {
          url,
          method: 'GET',
          params: {
            /* 
              params为需要传递给后端的查询数据,会通过 ' ? ' 以键值对的形式自动拼接在 url 之后;
              在Table组件中,该函数的形参 params 为 组件的 page 、size 和 sortable;
              也可以通过组件中使用 this.detailDS.setQueryParameter(para, value) 的方式来设置查询参数。
              para - 参数名、value - 参数值。
            */  
          },
        };
        return axiosConfig;
      },
      destroy: ({ data }) => {
        return {
          url: '',
          data,
          method: 'DELETE',
        };
      },
      update: ({ data, params }) => {
        return {
          url: ``,
          data,
          params,
          method: 'PUT',
        };
      },
      create: ({ data, params, deatSet }) => {
        return {
          url: ``,
          data,
          params,
          method: 'POST',
        };
      },
      submit: ({ data, params, dataSet }) => {
        // submit 适用于所有增删改操作,调用一次 submit 都会触发,后端通过 _status 来标识或识别 增/删/改 操作。
        // data 为 dataSet 对应的组件中的数据,需要注意的是只有当页面有改动的的时候,调用 submit / update / create / destroy 才会触发网络请求。
        const axiosConfig = {
          url: '',
          method: 'POST',
          data, // data 为需要传递给后端的数据,默认为形参中的data,即组件中的数据。 
        },
      return axiosConfig;
    },
  });
}
import React, { Component, Fragment } from 'react';
import { DataSet } from 'choerodon-ui/pro';

import DetailDS from './DetailDS'

export default class Detail extends Component {
  detailDS = new DataSet({
    ...DetailDS()
  })

  // 在页面上展示表格有两种方式:一种是直接在 Table 标签里面去写 Column;一种是将 Column 单独提出来。
  get columns() {
      return [
        { name: 'id', lock: 'left' },
        { name: 'employeeName', lock: 'left' },
        { name: 'employeeNumber', width: 150, lock: 'left' },
        { name: 'hiredate', lock: 'left' },
        { name: 'age', width: 80 },
        { name: 'enable', width: 80 },
      ]
  }

  buttons = [ 'add', 'save', 'delete' ]

  render() {
     /**
       buttons: Table 的功能按钮。可选值:add delete remove save query resetexpandAll collapseAll 
           export 或 数组 或 自定义按钮,数组为可选值字符串+按钮配置属性对象。
           给出的关键字在使用后可直接渲染出其功能按钮,并且其点击事件可直接触发 transport 中对应的方法。
       columns:表格的列。
       queryFieldsLimit:头部显示的查询字段的数量,超出限制的查询字段放入弹出窗口。
       columnResizable:可调整列宽。
     */
    return (
      <Fragment>
        <Table
          dataSet = { this.detailDS }
          buttons = { this.buttons }  
          columns = { this.columns } 
          queryFieldsLimit = { 2 }   
          columnResizable="true" 
        />
      </Fragment>
    )
  }
}


问题记录

choerodon 组件的问题

  1. remove(removeAll)和 delete(deleteAll) 的区别

delete 为立即删除,会去调用接口;remove 为临时删除操作,类似于你编辑了,但是没有保存,不保存重新查询数据就还在。

  1. 自定义 table 的搜索框

table 自定义搜索条

  1. lovPara 传一个变量

使用 dynamicProps 动态属性钩子或者对象。对象为字段属性和返回该字段值的钩子的键值对,建议使用对象以提高性能。

// 使用方法
ItemDynamicProps({ record }) {
  return {
    lovPara: {
      organizationId: record.get('organization') 
        ? record.get('organization').organizationId 
        : record.get('organizationId')
    }
  }
}
fields: [
   { 
      name: 'item', 
      type: 'object', 
      label: 'Item',
      lovCode: 'LOV_FND_ITEM', 
      dynamicProps: this.ItemDynamicProps, 
      ignore: 'always' 
   },  
]
  1. 自定义按钮,实现表格的新增、删除、查询和保存功能

让自定义的按钮触发注入在此表格的 dataSet 的对应 Method,Method 中的这些方法都是可以通过直接 ‘点’ 出来调用的。如 新增 - create、删除 - remove / removeAll / delete / deleteAll、查询 - query 等。

// 使用方法
add() {
  this.DetailDS.create();
}
delete() {
  // 需要注意的是,在调用 delete 和 remove 进行记录删除的时候,应传入需要删除的数据,此处以选择删除为例。
  // dataSet 的 currentSelected 为当前页的选中记录,包含当前页已选中的所有数据
  const { currentSelected } = this.DetailDS;
  this.DetailDS.delete(currentSelected);
}
  1. 在Form中使用DataSet时,配置了submitUrl,请求后无法自动处理Token

修改 .babelrc 文件,同 .babelrc

  1. 项目启动时报 cross-env 错误

一般是因为缺少 cross-env 模块,执行 yarn add cross-env 或 npm install cross-env 即可解决。

  1. dynamicProps设置lov值的时候,为什么会反反复复多次调用为dynamicProps设定的方法?

field 在获取任何属性的时候都会执行 dynamicProps,所以不要在 dynamicProps 里调用接口,dynamicProps也不支持async await。

  1. 如何手动获取到 dataSet 中的 data。

有两种方法: toData() 和 toJSONData()。
两种方法的区别:

  • toData() 会获取到当前 dataSet 中的全部数据,即使你的 fields 中有 ignore 属性,也不会过滤掉。
  • toJSONData() 获取到的是用于提交的 json 数据。需要注意的是,如果当前 dataSet 对应组件中的数据没有任何改动,则无法获取到该 dataSet 中的数据,提交只会提交变更的数据。
  1. 动态添加 dataSet 的 childrenDS,并把动态添加出来的 childrenDS 的数据渲染到页面中
// 在 dataSet 的 children 属性下添加
export default () => ({
  ...
  children: {
      DemandDateDS: new DataSet({ ...DemandDateDS() }),
  },
}
/*
 operationResponseDTOList 为后端返回给我的工序的数组,因为每个工序下面都有对应的 Task 需要操作,
所以我在这块每一个工序对应添加一个 dataSet,使用工序的 Code 作为 dataSet 的名字。
*/
operationResponseDTOList.map(item => {
   //  在组件中通过 “点” 的方式进行添加
   this.taskSplitDS.children[item.operationCode] = new DataSet({
    ...TaskSplitChildrenDS(),
    data: [].concat(item),
  });
})

在动态渲染 dataSet 的时候,需要注意 dataSet 的持久化,否则可能会出现调用 create 去添加数据的时候,每次都是初始化的状态。

  1. Table 的列添加 lock 属性之后,出现空白格。

给添加的 lock 的列设置宽度

  1. 筛选框有数据全部展示出来,并且可以多选

demo 预览
代码地址

  1. 刷新 Swagger - 解决 403

iam -> Permission_Refresh -> 先运行第二个,再运行第一个接口。服务名:light***,版本号:对应需要解决403的接口的版本号 version - x.x.x.RELEASE

  1. Table 组件第一列添加序号

利用变量和闭包的方式都不能实现 +1,需要利用当前 record 的 index 属性实现

{
  name: 'order',
  renderer: ({ record }) => record.index + 1,
},
  1. c7n 功能按钮的属性

自定义 save、add等组件给定的这些功能按钮的点击事件和按钮的展示内容

buttons = [
[ 'add', { children: '新增',  onClick: () = >{} ],
]
  1. 页面中使用别名引入图片
// images 是对应的路径别名
<img src={require('Images/emptyBox.png')}></img>
  1. 缓存当前页面的 state
    c7n 缓存组件
import cacheComponent from 'components/CacheComponent';

// cacheKey: 需要缓存的页面的路由
@cacheComponent({ cacheKey: '/employee-performance/index' })

React 框架的问题

  1. React 条件渲染组件之后,通过父子组件传参,props 拿到的不是最新的数据

setState 是异步的,它的第二参数是操作成功之后的一个回调。

// 当父组件中的 showTaskFlag 为 true 的时候,展示子组件,并调用子组件中的 getTaskData 方法。
  // 如果使用下面的写法,会出现 getTaskData 为 undefined
  handleShowTask(record) {
    const data = record.toData();
    this.setState({
      showTaskFlag: true,
    });
    this.getTaskData(data)  
  }
  // 正确的写法应该是将页面渲染之后,需要调用的函数写在 setState 的回调当中。
  handleShowTask(record) {
    const data = record.toData();
    this.setState({
      showTaskFlag: true,
    }, () => this.getTaskData(data));  
  }
  1. React 中遍历对象并渲染的方法
const obj = { name: '张小三' };
{
  Object.keys(obj).map(key => {
    return (
       <span> { obj[key] } </span>
    )
  });
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335