24 Node.js躬行记——低代码( 二 )


文章插图
编辑器默认是不支持放大的,这是自己加的一个功能 。点击放大按钮后,修改编辑器父级的样式,如下所示 , 全屏状态能更直观的修改代码 。
.fullscreen {position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 10000;}函数默认是字符串,需要进行一次转换,采用的是 new Function(),这种方式可以将参数传递进来 。eval() 虽然也能执行字符串代码,但是它不能传递上下文或参数 。
const stringToFunction = (func:string) => {const editorWarpper = new Function(`return ${func}`);return editorWarpper();};本来是想在编辑器中沿用 TypeScript 语法,但是在代码中没有编译成功,会报错 。
4)组件映射
一开始是想在编辑器中直接输入 JSX 代码,然后通过 Babel 转译,但在代码中引入 Babel 后也是出现了一系列的错误,只得作罢 。
之前的 parse() 函数可将字符串转换成组件,但是在实际开发,需要添加各种类型的属性,还有各类事件,全部揉成字符串并不直观 , 并且 antd 组件不能直接通过 parse() 解析得到 。所以仍然是书写一定规则的 Schema(如下所示),再转换成对应的组件 。
{name: "antd.TextArea",props: {width: 200},events: {onChange: function (dispatch, e) {const str = e.target.value;const keys = str.match(/\{(\w+)\}/g);const params = {};keys && keys.forEach((item) => (params[item] = {}));dispatch({type: "groupTemplate/setSqlParams",payload: params});}}};name 中会包含组件类别和名称,类别包括 4 种:antd、模板、HTML标准元素和自定义组件 。
【24 Node.js躬行记——低代码】export const componentHash:ObjectType = {admin: {Prompt,SelectTabs,CreateModal,},antd: {Affix,Anchor,AutoComplete,},html: {a: (node:JSX.Element|string, props = {}) => <a {...props}>{parse(node.toString())}</a>,p: (node:JSX.Element|string, props = {}) => <p {...props}>{parse(node.toString())}</p>,},custom: { ...Custom },};jsonToComponent() 是将JSON转换成组件的函数,就是从上面的对象中得到组件,带上属性、子组件后,再将其返回 。
const jsonToComponent = (item:JsonComponentItemType) => {const {name, props = {}, node,} = item;const names = name.split('.');const types = componentHash[names[0]];// 异常情况if (!types || names.length === 1) {return null;}const Component = types[names[1]];// HTML元素处理if (names[0] === 'html') {return Component(node, props);}// 组件处理if (node) { return <Component {...props}>{parse(node)}</Component>; }return <Component {...props} />;};5)关联组件
关联组件特指一个模板组件内包含另一个模板组件,例如标签栏组件,它会包含其他模板组件 。

24 Node.js躬行记——低代码

文章插图
如果要做到关联,最简单的方法是将组件的配置一起写到标签栏的参数中,但这么做会非常繁琐,并且内容太多 , 不够直观 。还不如跳过低代码平台,直接在编辑器中编写,来的省事 。
后面就想到关联组件索引 , 关联的组件也可以在平台中编辑自己的参数 。只是当组件删除后,关联的组件也要一并删除,代码的复杂度会变高 。
6)交互预览
在预览时,为了能实现交互,就需要修改状态驱动视图的更新 。
对于一些方法 , 在执行过后,就能实现状态或视图的更新 。
但对于一些属性,例如 values.allState,若要让其能动态读取内容,就需要借助 getter 。
const values:ObjectType = {get allState() {return wrapperState;},};二、配套设施要将该平台推广到内部使用,除了渲染引擎外,还需要些配套设施,包括自定义业务组件、页面呈现、持久化存储等 。
1)业务组件
内置的组件肯定是无法满足实际的业务,所以需要可以扩展业务组件,由此制订了一套简单的数据源规范 。所有的业务组件我都放到了custom文件中 , 可自行创建新文件,例如 demo 。
custom├──── demo├──── index.tsx├──── test.tsx在 index.tsx 文件中,会引入自定义的组件,后面就能在平台中使用了 。
import Demo from './demo';const Components:ObjectType = {Demo,};export default Components;为了便于调试,预留了测试组件的页面,在下拉框中选择相应的组件 , 并填写完属性后,就会在组件内容区域呈现效果 。
24 Node.js躬行记——低代码

文章插图
2)生成文件
在配置区域点击生成/更新文件后,就会将菜单、路由、权限等信息保存到 MongoDB 中 。其中最重要的就是组件的原始信息,如下所示 。

推荐阅读