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

在将参数转换类型后,接下来渲染引擎就会根据不同的组件对这些参数进行定制处理,例如将提示组件的 description 属性转换成 JSX 语法的代码 。parse()是一个解析函数,来自于 html-react-parser 库,可将组件转换成 React.createElement() 的形式 。回调函数的处理会在后面做详细的讲解 。
{handleProps: (values: ObjectType) => {// 将字符串转换成JSXif (values.description) {values.description = parse(values.description.toString());}return values;};}3)回调函数
除了 JSX 之外,为了能适应更多的业务场景,提供了自定义的回调函数 。
{props: {btns: `onClick: function(dispatch) {dispatch({type: "template/showCreate",payload: {modalName: 'add'}});`},name: "Btns"}编辑器组件使用的是 react-monaco-editor,即 React 版本的 Monaco Editor 。

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标准元素和自定义组件 。
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躬行记——低代码

文章插图
如果要做到关联,最简单的方法是将组件的配置一起写到标签栏的参数中,但这么做会非常繁琐,并且内容太多,不够直观 。还不如跳过低代码平台,直接在编辑器中编写,来的省事 。

经验总结扩展阅读