基于config-component转向面向数据的编程?

CodeCosmicRover
• 阅读 2649

面向数据编程

面向数据编程是什么样的体验?

其实是数据驱动式编程更向前走一步,我们知道现在MVVM框架,像React、vue、Angular这些给前端带来了很大的进步,更优雅的工程化体系结构,更健壮的代码体系结构。同样给开发者带来了数据驱动式开发的体验,但是业务代码还是经常会出现业务逻辑与UI表达形式的穿插混合的情况,很难统一。

github: https://github.com/chalecao/c...
感谢star!!!

样式行为分离

面向数据的编程其实核心思想还是做样式行为分离,中间的解耦利器便是数据。

样式 mix 行为 = 样式 + 数据 + 行为

于是我们抽象出来的config-component组件,作为驱动样式行为分离的通用组件,驱动面向数据编程。

例如实现下面的表单:

基于config-component转向面向数据的编程?

基于antd组件库,比较下不同的代码结构:

基于config-component转向面向数据的编程?

左边的图是基于ANTD正常的写法,我们要写Form,要写检验规则,要写子组件等等,关键是这些逻辑是糅合在一起的。右边是基于config-component提供的ConfigForm组件做了封装,只需要提供JSON schema配置数据即可驱动你的页面,分离数据校验和UI逻辑,UI逻辑基于UIconfig,数据校验基于schema做校验。

creative feature创新特性

✅ change your code style to face data, use JSON schema config to driven you page.数据驱动式开发更进一步转向面向数据编程,结合React Hooks开发更高效,专注于数据和业务逻辑.基于JSON配置数据驱动你的页面或者表单。

✅ add schema mechanism to ensure you data correct and force you to care you data and handle the abnormal situation.开发中引入schema机制验证核心数据的正确性,无论是表单还是前台组件均可适用。

✅ support get data async, verify data when it changes.基于schema动态校验数据,支持异步数据更新,响应式做校验。

usage用法

安装:

npm install config-component --save

config-component默认提供了2中类型组件,

  • ConfigComponent, 通用类型组件,配置页面逻辑,用于前台页面
  • ConfigForm, 专用于配置化表单,可以用中后台页面

For common component:

import {ConfigComponent} from 'config-component'
...
<ConfigComponent
      initialValues={...}
      schema={...}
      uiConfig={...}
      />

For form component:

import {ConfigForm} from 'config-component'
...
<ConfigComponent
      initialValues={...}
      schema={...}
      uiConfig={...}
      onSubmit={()=>{...}}
      componentSet={...}
      />

params:

ℹ️schema: the core data you care, ConfigComponent will verify you core data with schema,you can specify alt props in item, when error occurs, will show alt as default value

ℹ️initialValues: init value in you comp

ℹ️uiConfig: define your ui interface with json config, support event hooks, see example in playground file.

ℹ️onSubmit: used only in form when submit data.

ℹ️componentSet: support Ant Design or Fusion or you selfdefine Components.


代码示例:

import React, { useContext } from 'react'
import * as yup from 'yup'
import * as AntdComponents from 'antd'
import moment from 'moment'
import { ConfigForm } from 'config-component'
import 'antd/dist/antd.css'

const schema = yup.object().shape({
  firstName: yup.string().required(),
  lastName: yup.string().required(),
  startTime: yup.array().required(),
  useTime: yup.array().required().when('startTime', (startTime, schem) => {
    return schem.test(
      'check-start',
      'useTime required',
      value => {
        return !!value
      },
    ).test(
      'check-start',
      'useTime start >= startTime start',
      value => {
        return value && startTime[0].milliseconds(0).valueOf() <= value[0].milliseconds(0).valueOf()
      },
    ).test(
      'check-end',
      'useTime end >= startTime end',
      value => {
        return value && startTime[1].milliseconds(0).valueOf() <= value[1].milliseconds(0).valueOf()
      },
    ).required()
  }),
  agree: yup.boolean().required().test(
    'check-agree',
    'agree must checked',
    value => {
      return !!value
    },
  ).required(),
})

const initialValues = {
  firstName: 'Tony',
  lastName: 'Stark',
  startTime: [moment('2019-09-01'), moment('2019-09-03')],
}

export default function App() {

  const formConfig = {
    initialValues,
    schema,
    onSubmit: values => console.log('Your values are:', values),
    componentSet: AntdComponents,
  }

  const formItemLayout = {
    labelCol: {
      xs: { span: 24 },
      sm: { span: 8 },
    },
    wrapperCol: {
      xs: { span: 24 },
      sm: { span: 16 },
    },
  }
  const tailFormItemLayout = {
    wrapperCol: {
      xs: {
        span: 24,
        offset: 0,
      },
      sm: {
        span: 16,
        offset: 8,
      },
    },
  }

  const onChangeWrapper = schemaKey => (form, e) => {
    const { onChange, value } = form.getFieldProps(schemaKey)
    console.log('prevalue', value)
    onChange(e)
  }

  return (
    <ConfigForm
      {...formConfig}
      uiConfig={{
        layout: formItemLayout,
        items: [
          {
            label: 'First Name: ',
            comp: 'Input',
            schemaKey: 'firstName',
            props: {},
          },
          {
            label: 'Last Name: ',
            comp: 'Input',
            schemaKey: 'lastName',
            props: {
              onChange: onChangeWrapper('lastName'),
            },
          },
          {
            label: 'Start Time: ',
            comp: 'DatePicker.RangePicker',
            schemaKey: 'startTime',
            props: {},
          },
          {
            label: 'Use Time: ',
            comp: 'DatePicker.RangePicker',
            schemaKey: 'useTime',
            props: {},
          },
          {
            layout: tailFormItemLayout,
            comp: [
              {
                comp: 'Checkbox',
                schemaKey: 'agree',
                props: {
                  color: '#999',
                },
              },
              {
                comp: 'span',
                children: '同意协议',
                props: {
                  style: {
                    marginLeft: '10px',
                    color: '#999',
                  },
                },
              },
            ],
            props: {},
          },
          {
            type: 'submit',
            layout: tailFormItemLayout,
            comp: [
              {
                type: 'submit',
                comp: 'Button',
                children: '提交',
                props: {
                  type: 'primary',
                  htmlType: 'submit',
                  key: 'submit',
                },
              },
              {
                type: 'reset',
                comp: 'Button',
                children: '重置',
                props: {
                  type: 'primary',
                  key: 'reset',
                  style: { marginLeft: '10px' },
                },
              },
            ],
            props: {},
          },
        ],

      }}
    />
  )
}

online example在线案例

playground:https://chalecao.github.io/co...

example - configForm

online example: https://codesandbox.io/s/conf...

example - configComponent

online example: https://codesandbox.io/s/conf...

总结

面向数据的编程,核心关注数据

参考

fed123前端学堂

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Java修道之路,问鼎巅峰,我辈代码修仙法力齐天
<center<fontcolor00FF7Fsize5face"黑体"代码尽头谁为峰,一见秃头道成空。</font<center<fontcolor00FF00size5face"黑体"编程修真路破折,一步一劫渡飞升。</font众所周知,编程修真有八大境界:1.Javase练气筑基2.数据库结丹3.web前端元婴4.Jav
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Easter79 Easter79
3年前
SwiftUI 跨组件数据传递
作者:Cyandev,iOS和MacOS开发者,目前就职于字节跳动0x00前言众所周知,SwiftUI的开发模式与React、Flutter非常相似,即都是声明式UI,由数据驱动(产生)视图,视图也会与数据自动保持同步,框架层会帮你处理“绑定”的问题。在声明式UI中不存在命令式地让一个视图变成xxx
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(