从零实现一套低代码(保姆级教程) --- 【5】实现组件和属性面板的交互

摘要

在上一篇中,我们简单实现了右侧属性面板。可以通过更改按钮文字,重新渲染Button组件。
目前来到了本系列的第五章,本篇主要是实现Button组件的全部属性配置。

如果你是第一次看本系列中的文章,建议可以先看一下第一节:
从零实现一套低代码(保姆级教程) — 【1】初始化项目,实现左侧组件列表

在第一节中,说了本系列会实现出什么样的低代码项目。同时对技术栈等相关因素进行了分析。但是本系列因为是对线上例子的重构,所以实现的可能会有所差异。

关于属性面板的配置,可能是整个系列中比较重要的。因为低代码主要的想法就是通过可视化的配置来决定页面的结构和样式。那么如果属性这一章节可以通透起来,后面的样式,动作等配置都是手到擒来了。

OK,话不多说,咱们开始继续实现。

在这里插入图片描述

1.不同组件的配置

我们在上一节,只是简单实现了按钮文字的配置。那思考一个问题,对于不同的组件来说,属性面板中的配置一定也是不一样的。例如按钮组件有按钮文字,图标组件有图标类型。。。

所以,我们用一个utils文件,去管理不同组件的属性配置。我们在rightPart下新增一个文件夹staticUtils,用来存放相关的utils方法和变量。

在这里插入图片描述

在attributeMap里面,我们用来保存不同组件需要展示的属性配置。那么组件的属性配置在哪里可以看到呢?我们需要来到antD的官网:
https://ant-design.antgroup.com/components/button-cn#api
可以看到,在官网中,Button组件的属性配置都在这里了。

在这里插入图片描述

那我们希望的是,可以在我们的低代码平台中,通过属性面板中的配置,去改变按钮相关的属性。所以我们在attributeMap中,将对应的组件属性写下来。

interface AttributeMap {[key: string]: ComAttribute[]
}interface ComAttribute {label: string,value: string
}const buttonAttribute: ComAttribute[] = [{label: '设置按钮文字',value: 'caption'},{label: '设置危险按钮',value: 'danger'},{label: '设置按钮禁用',value: 'disabled'},{label: '设置幽灵按钮',value: 'ghost'}, {label: '设置按钮形状',value: 'shape'},{label: '设置按钮大小',value: 'size'}
]const attributeMap: AttributeMap = {Button: buttonAttribute
}export {attributeMap
}

2.在属性面板中展示

OK,现在我们已经写完了对于Button组件所有的属性配置(当然不是antD中的所有,只选了一部分)。
现在我们需要再属性面板中,将这些属性展示出来。回到rightPart中的index.tsx中。

修改getAttributePanel方法:

  import { attributeMap } from './staticUtils/attributeMap';const getAttributePanel = () => {const comType = window.renderCom?.comType;// 拿到组件对应的属性列表const comAttributeList = attributeMap[comType] || []return <div>{comAttributeList.map((item,index) => {return <div key={index} className='attributeItem'><label className='attributeLabel'>{item.label}</label><div className='attributeItemValue'><Input onChange={changeComAttribute(item.value)} /></div></div>})}</div>}const changeComAttribute = (value: string) => {return (e: any) => {window.renderCom[value] = e.target.value;window.setComList([...window.comList])}}

然后我们再修改一下属性标题的样式。

.attributeLabel {width: 200px;margin-top: 5px;margin-right: 15px;white-space: nowrap; /* 防止文字换行 */overflow: hidden; /* 隐藏超出部分 */text-overflow: ellipsis; /* 超出部分显示省略号 */
}

写完之后,你会发现。当我点击组件的时候,右侧的属性面板没有什么变化,这是为什么呢?因为目前我们实现的方案是通过windows来传递组件信息,所以不会引起组件的render。

所以我们可以手动触发一下组件的render方法,就在切换tab页签的时候,更新一下组件

  const [update, setUpdate] = useState({})const onChange = (value: string) => {setUpdate({a: 123})}

这个时候,当你选中某一个组件时,再切换一下页签,就可以看到属性面板了!!!

在这里插入图片描述

这里我们注意下,因为之前我们在将组件拖拽到画布区后,没有在window上挂载组件,所以没有效果。所以这里必须点击按钮之后,renderCom才会挂载在window上。所以我们回到mainPart中修改一下。

  const onDrop = (e: any) => {// 修改的部分const comNode = {comType: window.nowCom,style,comId}comList.push(comNode)window.renderCom = comNode;window.comList = comList;window.setComList = setComListsetSelectId(comId)}setComList([...comList])}

3.属性面板组件

OK,现在我们右侧属性面板已经展示了属性配置。但是呢,有一个问题是,比如控制按钮的显示和隐藏,我不需要使用文本框来控制,应该是一个开关来控制。

所以,对于不同的属性,我们要有不同的组件来控制它的值。
所以我们修改一下attributeMap文件:

interface AttributeMap {[key: string]: ComAttribute[]
}interface ComAttribute {label: string,value: string,type: string,options?: Array<any>,defaultValue?: string
}const buttonAttribute: ComAttribute[] = [{label: '设置按钮文字',value: 'caption',type: 'input'},{label: '设置危险按钮',value: 'danger',type: 'switch'},{label: '设置按钮禁用',value: 'disabled',type: 'switch'},{label: '设置幽灵按钮',value: 'ghost',type: 'switch'}, {label: '设置按钮形状',value: 'shape',type: 'select',options: [{value: 'default'},{value: 'circle'},{value: 'round'}],defaultValue: 'default'},{label: '设置按钮大小',value: 'size',type: 'select',options: [{value: 'large'},{value: 'middle'},{value: 'small'}],defaultValue: 'default'}
]const attributeMap: AttributeMap = {Button: buttonAttribute
}export {attributeMap
}

在这里我们加一个type值,用来控制属性的配置组件。这里我们有三个值,input,select,switch分别代表输入框,下拉框和开关。

而options代表的是下拉框中的可选项,defaultValue代表默认值。

在getAttributePanel方法里,我们不能无脑的返回Input组件了,我们需要根据属性的type值,来返回不同的组件。

  const getAttributePanel = () => {const comType = window.renderCom?.comType;const comAttributeList = attributeMap[comType] || []return <div>{comAttributeList.map((item,index) => {return <div key={index} className='attributeItem'><label className='attributeLabel'>{item.label}</label><div className='attributeItemValue'>// 根据组件的type,返回不同的组件<InputComponent {...item} onChange={changeComAttribute(item.value)}/></div></div>})}</div>}

我们创建一个staticComponet目录,用来保存公共的组件,在目录下新增InputComponent组件。
在这里插入图片描述

import { Input, Switch, Select} from "antd"export default function InputComponent(props: any) {const { onChange, type, defaultValue, options } = propsconst getComponent = () => {switch (type) {case 'input': {return <Input style={{width:'120px'}} defaultValue={defaultValue} onChange = {onChange}/>}case 'switch': {return <Switch defaultValue={defaultValue} onChange = {onChange}/>}case 'select': {return <Select style={{width:'120px'}}  options={options} defaultValue={defaultValue} onChange={onChange}></Select>}}}return (<div>{getComponent()}</div>)
}

做完这些,我们右侧的属性面板就已经很像那么回事了!!!!

在这里插入图片描述

现在还有一个问题是,对于右侧,不管是Input还是Select,它们走的都是一个onChange

有的组件是通过e.target,有的是直接拿即可。
所以我们要对onChange方法进行兼容,现在我们修改我们的changeComAttribute方法:

  const changeComAttribute = (value: string) => {return (e: any) => {let attribute = e;if(typeof e === 'object') {attribute = e.target.value;}window.renderCom[value] = attribute;window.setComList([...window.comList])}}

现在你可以通过更改右侧属性面板,然后在控制太查看renderCom的值是否发生了变化:

在这里插入图片描述

4.组件针对属性的渲染

还记得我们之前是怎么通过更改按钮文字来让组件冲新渲染的嘛?一样的道理,现在我们来修改一下按钮的其他属性。

import { Button as AntButton } from 'antd'export default function Button(props: any) {const { caption, danger, disabled, ghost, shape, size} = propsreturn (<div><AntButtondanger={danger}disabled={disabled}ghost={ghost}shape={shape}size={size}>{caption || '按钮'}</AntButton></div>)
}

现在你就可以通过属性面板的配置,促使组件的渲染了!!!!

在这里插入图片描述

到这里,这一篇讲的内容就完事了。

本章内容会提交在github上:
https://github.com/TeacherXin/XinBuilder2
commit: 第五节:实现组件和属性面板的交互

如果可以的话,可以给博主的GitHub点亮一颗小星星(╹▽╹)

博主补充

如果Button组件已经实现了的话,读者是否可以将Input的属性面板和组件也实现了呢?也是同样的道理,这部分内容,我会在github上进行提交,就不再重复讲解了。
本章内容会提交在github上:

https://github.com/TeacherXin/XinBuilder2
commit: 第五节:实现Input组件的属性配置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/298960.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【adb】电脑通过ADB向手机传输文件

具体步骤如下&#xff1a; Step1 下载ADB工具 下载最新版本的 ADB工具 !!! 注意&#xff1a;一定要是最新版本的ADB&#xff0c;否则很可能导致无法识别到手机。 将下载的ADB解压以后的文件如下图所示&#xff1a; Step2 添加环境变量 将 ADB的路径 D:\platformtools &…

YOLO算法改进7【中阶改进篇】:主干网络C3替换为轻量化网络MobileNetV3

解决问题&#xff1a;YOLOv5主干特征提取网络采用C3结构&#xff0c;带来较大的参数量&#xff0c;检测速度较慢&#xff0c;应用受限&#xff0c;在某些真实的应用场景如移动或者嵌入式设备&#xff0c;如此大而复杂的模型时难以被应用的。首先是模型过于庞大&#xff0c;面临…

MySQL运维实战(1.3)安装部署:源码编译安装

作者&#xff1a;俊达 引言 在大多数情况下&#xff0c;我们不需要自己编译MySQL源码&#xff0c;因为编译的MySQL和二进制包的内容基本一致。然而&#xff0c;有些特殊情况可能需要我们采用源码编译的方式安装MySQL&#xff1a; 安装非标准版本的MySQL&#xff1a;有些特殊…

轻松管理固定资产,易点易动固定资产管理系统为企业开启新篇章

在现代企业运营中&#xff0c;固定资产管理是一个不可忽视的关键环节。有效地管理和维护固定资产不仅可以提升企业运营效率&#xff0c;还能最大限度地发挥资产的价值。为了满足企业对固定资产管理的需求&#xff0c;我们推出了易点易动固定资产管理系统&#xff0c;一款功能强…

PyTorch官网demo解读——第一个神经网络(3)

上一篇&#xff1a;PyTorch官网demo解读——第一个神经网络&#xff08;2&#xff09;-CSDN博客 上一篇文章我们讲解了第一个神经网络的模型&#xff0c;这一篇我们来聊聊梯度下降。 大佬说梯度下降是深度学习的灵魂&#xff1b;梯度是损失函数&#xff08;代价函数&#xff…

labelme目标检测数据类型转换

1. labelme数据类型 LabelMe是一个开源的在线图像标注工具&#xff0c;旨在帮助用户创建和标记图像数据集。它提供了一个用户友好的界面&#xff0c;让用户可以直观地在图像上绘制标记框、多边形、线条等&#xff0c;以标识和注释图像中的对象或区域。 GitHub&#xff1a;http…

python使用apscheduler定时任务,固定周几运行程序

在add_job中添加参数day_of_week即可&#xff1a; day_of_week "0"表示&#xff1a;只有周一运行day_of_week "0-4"表示&#xff1a;周一到周五运行day_of_week "0,1,2"表示&#xff1a;周一二三运行 示例程序 from datetime import datet…

Docker介绍、常用命令与操作

Docker介绍、常用命令与操作 学习前言为什么要学习DockerDocker里的必要基础概念常用命令与操作1、基础操作a、查看docker相关信息b、启动或者关闭docker 2、容器操作a、启动一个镜像i、后台运行ii、前台运行 b、容器运行情况查看c、日志查看d、容器删除 3、镜像操作a、镜像拉取…

Unity网格篇Mesh(一)

Unity网格篇Mesh&#xff08;一&#xff09; 本文的目标1.渲染仔细看下面的图你会发现&#xff0c;锯齿状 2.创建网格顶点4 x 2网格网格的顶点 3.创建网格网格只在Play模式下显示逆时针和顺时针三角形第一个三角面一个四边形由两个三角面组成第一个四边形填充剩余网格 接下一篇…

Wordpress对接Lsky Pro 兰空图床插件

Wordpress对接Lsky Pro 兰空图床插件 wordpress不想存储图片到本地&#xff0c;访问慢&#xff0c;wordpress图片没有cdn想要使用图床&#xff0c;支持兰空自定义接口 安装教程—在wp后台选择插件zip—然后启用—设置自己图床API接口就ok了&#xff0c;文件全部解密&#xff0c…

LazyForEach常见使用问题

目录 1、渲染结果非预期 2、重新渲染时图片闪烁 3、ObjectLink属性变化UI未更新 上篇文章中我们介绍了LazyForEach的基本使用&#xff0c;展示了如何使用LazyForEach构造一个列表&#xff0c;并演示数据的添加、删除、修改如何与LazyForEach配合并正确的更新UI。本篇将介绍使…

全自动洗衣机什么牌子好?最好用的四款内衣洗衣机推荐

随着科技的快速发展&#xff0c;现在的人们越来越注重自己的卫生问题&#xff0c;不仅在吃上面会注重卫生问题&#xff0c;在用的上面也会更加严格要求&#xff0c;而衣服做为我们最贴身的东西&#xff0c;我们对它的要求也会更加高&#xff0c;所以最近这几年较火爆的无疑是内…