1 Star 0 Fork 1

yiru / web-design

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

低代码(low-code)简单实践

GitHub license npm version GitHub Workflow Status (with branch)

Web Design 是一个简单的低代码开发平台,用于快速搭建项目、开发页面、配置接口等。

Web Design 使用可视化操作生成页面描述 json schema,然后通过自定义规则将 json schema 渲染成目标页面来实现页面可视化开发。

Web Design 基于 huxy-admin 模板创建。除了提供页面可视化搭建,还包含了工程化配置、主题设计、Layout 设计、API 配置、权限和 i18n 配置等。

详细功能介绍:系统功能

理解

低代码就是尽量少写代码,定义好业务组件,通过可视化操作实现开发工作。它主要受众是开发者。

无代码(no-code)即不需要写代码就能完成开发,更加偏向业务层的定制。

解决了什么?

提效降本、质量保障、降低开发门槛。

低代码可以提升开发效率,保障系统稳定性,也降低了开发门槛,可以直接可视化开发。

可能存在的问题

  • 不灵活。适用于通用业务领域,对定制化需求不友好。
  • 不可控。业务拓展性、可维护性较低。
  • 不好用。开发不想用,业务不会用。

低代码或许可以降低开发门槛,但复杂度并不会降低。可视化开发的自由度越高,组件粒度就越细,配置复杂度就越高。

简单实践

前端低代码开发不仅是界面开发,应该还包含工程化、项目管理、api 接口、权限控制等一些列的开发提效。

设计

一个页面其实就是一棵树,所以不管是拖拽还是配置,最终完成的就是一棵数据树。所以我们可以通过json schema来进行页面设计。

实现

基础搭建

工程化layout 设计权限和 i18nAPI 管理 这些都是一些管理平台的基础设施,前面也讲过,大家可以去看看。

页面设计

schema 设计

const schema = {
  type: 'a',
  props: {},
  children: [],
};
  • type:标签名或组件名。组件可以是 UI 组件或业务组件,先注册再使用。
  • props:属性配置。组件的属性可根据组件库或自定义组件使用文档去配置。如果属性里面含有组件,可依照 schema 渲染原则执行。
  • children:子节点。可以是文本节点,组件,或子元素列表。

custom render

const render = (schema, params) => {
  schema = Array.isArray(schema) ? schema : [schema];
  const dom = schema.map((item, i) => {
    let {type, props, children} = item;
    type = (type || 'div').trim();
    const first = type.charAt(0);
    type = first.toUpperCase() === first ? components[type] || 'div' : type;
    props = {
      key: i,
      ...formatProps(props, params),
    };
    children = Array.isArray(children) ? render(children, params) : [formatChildren(children || props.children, params) ?? null];
    return createElement(type, props, ...children);
  });
  return dom;
};
  • components:我们注册的组件。
  • formatProps、formatChildren:将 props 或 children 转换为我们需要的运行时的值。主要用于我们自定义的组件。props 或 children 可以是函数,可以传递我们需要的参数 params,最终返回我们需要的数据。
  • render:通过 react 的 createElement(type,props,...children) 渲染。

属性解析

const render = (schema, params) => {
  schema = Array.isArray(schema) ? schema : [schema];
  const dom = schema.map((item, i) => {
    let {type, props, children} = item;
    type = (type || 'div').trim();
    const first = type.charAt(0);
    type = first.toUpperCase() === first ? components[type] || 'div' : type;
    props = {
      key: i,
      ...formatProps(props, params),
    };
    children = Array.isArray(children) ? render(children, params) : [formatChildren(children || props.children, params) ?? null];
    return createElement(type, props, ...children);
  });
  return dom;
};

可使用自定义函数,组件内部数据作为参数,来获取属性值。或直接使用全局 configs。

例如:

{
  prop:'test',
  isPending:`{true}`,
  style:`{{width:'800px'}}`,
  handle:`{self=>self.rules}`,
  onClick:`{()=>e=>alert('hello')}`,
}

通过 {code} 将 code 字符串转换为运行时代码。

判断并提取字符串代码

const matchedStr = (str, c = ['{', '}']) => str?.trim?.().match(new RegExp(`^${c[0]}([\\s\\S]*)${c[1]}$`))?.[1];

执行字符串代码

const str2code = (str, hasReturn = false) => {
  str = hasReturn ? str : `return ${str};`;
  const exec = Function(str);
  return exec();
};

str2code 会直接执行并返回结果,如果返回的是函数会执行函数并返回结果。如果我们需要返回函数,就要包裹一层函数。例如:onClick{()=>e=>alert('hello')}

路由设置

路由配置可直接在页面配置,存入后台,使用时获取路由配置即可。

{
  path:'/low-code',
  name:'低代码',
  icon:'CoffeeOutlined',
  denied:false,
  children:[
    {
      path:'/dom',
      name:'原生dom',
      icon:'CodeOutlined',
      componentPath:'/lowCode',
      loadData:{
        pageSchema,
      },
    },
    {
      path:'/ui',
      name:'UI组件',
      icon:'CodeOutlined',
      componentPath:'/lowCode',
      loadData:{
        pageSchema,
      },
    },
    {
      path:'/users',
      name:'业务组件',
      icon:'CodeOutlined',
      componentPath:'/lowCode',
      loadData:{
        pageSchema,
      },
    },
    {
      path:'/users/add',
      name:'新增用户',
      componentPath:'/lowCode',
      loadData:{
        pageSchema,
      },
    },
    {
      path:'/users/edit/:id',
      name:'编辑用户',
      componentPath:'/lowCode',
      loadData:{
        pageSchema,
      },
    },
  ],
}

如果整个系统都是通过 schema 数据配置生成的,那么我们只需一个渲染器,通过路由 id 获取到 shcema 数据,然后渲染成当前路由页面。所以只需一个渲染文件即可。

根据 projectIdrouterId 获取路由页面数据。

const pageSchema = async ({id}) => {
  const {result} = await apiList.listSchemaFn({routerId: id, projectId: defProject._id});
  return {result};
};

通过设置路由 loadData 来提前请求数据,页面直接获取即可。详细使用见 useRouter

const pageSchema = async ({id}) => {
  const {result} = await apiList.listSchemaFn({routerId: id, projectId: defProject._id});
  return {result};
};

页面渲染

const Index = props => {
  const {pageSchema} = props;
  if (pageSchema == null || pageSchema.pending) {
    return <Spinner global />;
  }
  return customRender(pageSchema.result || [], {}, props);
};

可视化开发示例

创建项目

1

首先我们创建一个项目,如图所示。本示例使用 控制台 项目演示。

2

创建用户并分配项目

3

创建 API

4

5

新建项目路由

6

为用户设置路由权限

7

页面设计

原生 html 标签

10

23

根据 dom 元素属性自行配置。

UI 组件

12

14

当我们设计好页面时,可以随时回到项目路由查看改页面,也可点击预览查看,符合预期效果后保存即可。

22

25

原生标签和基础组件只能设计出一些静态展示效果,我们可以自定义一些业务组件,给页面加入交互性。

业务组件

tableform 为例,简单设计一个用户管理页面。

15

table 设置了自定义属性 actions columns searchSchema modalSchema

{
  actions,
  columns,
  searchSchema,
  modalSchema,
}
  • actions:定义事件
  • columns:表头设计
  • searchSchema:搜索表单
  • modalSchema:弹窗表单

16

事件定义可自行定义 action name ,共页面使用,apiName 从我们 API 系统里面选。

预览

17

可实时进行页面预览,也提供了撤销重做操作。

编辑功能

props 编辑

const editProps = values => {
  const tree = editNodes(schemaTree, selectedKey, {props: values}, 'key');
  setSchema(tree);
  record(clone(tree));
  setDisableUndo(false);
};

每次编辑都会触发 schema 更新,并会记录每次操作的数据,使用 record 函数记录,便于我们完成撤销重做功能。

cacheData 函数

const {record, undo, redo, clean} = cacheData();

撤销重做

const undoDesign = () => {
  const {index, data} = undo();
  setSchema(data);
  if (index === 0) {
    setDisableUndo(true);
  }
  setDisableRedo(false);
};

const redoDesign = () => {
  const {index, length, data} = redo();
  setSchema(data);
  if (index === length - 1) {
    setDisableRedo(true);
  }
  setDisableUndo(false);
};

组件移动

提供了组件移动功能,可根据需要自行拖动。

27

const onDrop = info => {
  const fromId = info.dragNode.key;
  const toId = info.node.key;
  const dropPosition = info.dropPosition;
  const tree = moveNodes(schemaTree, fromId, toId, dropPosition, 'key');
  setSchema(tree);
};

效果

可点击按钮或链接查看效果。

28

页面 schema

29

用户管理页面

18

页面 schema

30

编辑页面

19

页面 schema

31

总结

低代码更多的是用来当作提升开发效率的一个工具,在我们当前业务范围内,写少量代码封装好业务组件,即可进行可视化开发。

平台的通用性和灵活性,需要我们在实际业务中去权衡。

我们需要认清,没有一劳永逸的方法,只有在不断探索中提升。

项目地址:https://github.com/ahyiru/web-design

MIT License Copyright (c) 2021 yiru Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

low-code development platform 展开 收起
JavaScript 等 5 种语言
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
JavaScript
1
https://gitee.com/yiru/web-design.git
git@gitee.com:yiru/web-design.git
yiru
web-design
web-design
master

搜索帮助