从零实现一套低代码(保姆级教程) --- 【4】实现右侧属性面板

news2025/2/2 3:00:52

摘要

继画布区的实现之后,来到本系列的第四篇文章,如果你没有看过之前的文章,可以建议先看一下第一篇文章,里面介绍了要实现的项目,是否是你要学习的内容,再决定是否要学习这一些列的文章。
从零实现一套低代码(保姆级教程) — 【1】初始化项目,实现左侧组件列表

在上一篇中,我们实现了画布区的渲染,同时也支持了组件在画布区的随意拖拽布局。
所以我们实现出的低代码项目,在画布区的布局方式是自由布局。

同时在上一篇的结尾,也把Input组件的实现补充了(没有在文章体现,在GitHub上的提交记录可以看到)。

目前我们的项目是长这个样子的。

在这里插入图片描述
那如果我们只能拖拽组件,并不能对组件进行修改,那这个低代码就很无用了,所以这一篇。我们主要来实现右侧属性面板。

能够通过可视化的配置,来修改组件的属性。比如我想通过一个开关,来控制按钮的显示与隐藏,通过一个输入框,来控制按钮的文本。

OK,垃圾话就不说太多了,我们开始实现这一部分内容。

在这里插入图片描述

1.实现右侧面板结构

现在请读者打开rightPart下的index.tsx文件;

对于右侧的属性面板,我们可以参考左侧的面板,样式都一样,只不过定位后,属性面板的right值应该为0。

同时我们要思考一个问题,在项目的后期,我们可能不止可以修改组件的属性,也可以修改组件的样式,或者其他配置。所以我们可以在右侧的面板上,实现一个多页签。当然现在,我们只实现属性的面板。

import './index.css'
import { Tabs } from 'antd';
import type { TabsProps } from 'antd';

export default function RightCom() {

  const getAttributePanel = () => {
    return <div></div>
  }

  const items: TabsProps['items'] = [
    {
      key: 'attributePanel',
      label: <div style={{fontSize:'18px',width:'100px',textAlign:'center'}}>属性</div>,
      children: getAttributePanel(),
    },
    {
      key: 'stylePanel',
      label: <div style={{fontSize:'18px',width:'100px',textAlign:'center'}}>样式</div>,
      children: 'Content of Tab Pane 2',
    }
  ];

  const onChange = () => {
    
  }

  return (
    <div className='rightCom'>
      <Tabs defaultActiveKey="1" items={items} onChange={onChange} />
    </div>
  )
}

.rightCom {
  width: 20%;
  position: absolute;
  right: 0;
  top: 10%;
  background-color: white;
  height: 90%;
}

我们实现出来的效果就是:

在这里插入图片描述

写到现在,是不是已经有点低代码的样子了,已经像回事了是吧。不要开心太早,后面还有很多的内容需要写。。。。 ̄□ ̄||

2.实现组件的点击选中

那我们想一下,对于右侧的属性面板。我们在什么时机去展示呢

在网站的例子上,大家可以尝试一下,我在第一版实现的时候,是通过右键组件,然后选择设置属性,就会展示属性面板。

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
XinBuilder 点击跳转

但是我觉得这种方式不是很友好,很多第一次打开的人不知道。所以在这个版本我准备换一种实现思路,点击组件的时候直接触发属性面板的显示。

OK,那我们现在就要回到mainPart中了,我的点击事件写在哪里呢?记得之前拖拽的事件写在哪了吗,我们就写在那里!!!!但是为了结构比较清晰,还是在外面包一层div用来转本展示选中的样式。

第二个问题是,在画布区我们怎么知道选中的是哪个组件呢?我们可以将组件的border设置为蓝色,这样我们就可以知道选中的是哪一个组件了!

这个时候,为了保证组件的唯一性,你就会发现,我们必须要给组件一个ID了,我们用时间戳来给组件一个comId。
interface ComJson {
  comType: string,
  // 组件的唯一ID
  comId: string,
  style?: any
}

// 当前选中节点的comId
const [selectId, setSelectId] = useState<string>('')

const onDrop = (e: any) => {
// 其他代码
   if(window.nowCom === 'renderCom' && dragCom && dragCom.style) {
	// 其他代码
   }else{
  // 其他代码
     comList.push({
       comType: window.nowCom,
       style,
       // 通过时间戳生成comId
      let comId = `comId_${Date.now()}`
      comList.push({
        comType: window.nowCom,
        style,
        comId
      })
      setSelectId(comId)
     })
   }
   setComList([...comList])
}
  const selectCom = (com: ComJson) => {
    return () => {
      // 点击事件设置选中节点的ID
      setSelectId(com.comId)
    }
  }
  
  return (
    <div onDrop={onDrop} onDragOver={onDragOver} onDragEnter={onDragEnter} className='mainCom'>
      {
        comList.map(com => {
          const Com = components[com.comType as keyof typeof components];
          // 这里可以把key加上了
          return <div key={com.comId} onClick={selectCom(com)} draggable onDragStart={onDragStart(com)}>
          	// 触发点击事件,新加的div
            <div className={com.comId === selectId ? 'selectCom' : ''} style={com.style}>
              <Com />
            </div>
          </div>
        })
      }
    </div>
  )
.selectCom{
  border: 0.5px solid #1677ff;
}


这里一定要注意的是,我把Com的style提到了外层div上,因为这个style里面包含的内容主要是和位置相关的,我们没必要将其挂载在组件上。一定要修改一下,不然你的项目会有问题的,一拖拽就把其他的元素带起来

现在我们就实现了画布区节点选中的状态。

在这里插入图片描述

3.渲染右侧属性面板

当我们在画布区选中某个节点的时候,要怎么通知右侧属性面板展示对应组件的属性配置呢?
这就涉及到跨组件传递数据的内容了。

其实从左侧的组件到画布区这一个过程,我就提到过,后面我们会用redux来进行状态管理,而全量的组件,正适合在redux中进行管理。但是和redux相关的内容,我会专门用一章节去实现,所以现在,我们依旧先挂载在window上。

  const selectCom = (com: ComJson) => {
    return () => {
      setSelectId(com.comId);
      // 挂载在window上,后面会使用redux进行替换
      window.renderCom = com;
      window.comList = comList;
      window.setComList = setComList
    }
  }

我们先将当前组件,以及触发画布区重绘的方法挂载在window上。

现在我们回到rightPart下。我们在右侧面板先只展示一个输入框,那这个输入框用来干什么呢?用来更改按钮的文字!!!!!

  const getAttributePanel = () => {
    return <div>
      <div className='attributeItem'>
        <label>按钮文字:</label>
        <div className='attributeItemValue'>
          <Input onChange={changeComAttribute} />
        </div>
      </div>
    </div>
  }

  const changeComAttribute = () => {

  }
.attributeItem{
  width: 200px;
  height: 60px;
  display: flex;
  justify-content: space-between;
}

OK。现在我们在onchange方法里面,更改当前组件的按钮文字。这里我们起一个caption名称

  const changeComAttribute = (e:any) => {
    window.renderCom.caption = e.target.value;
    window.setComList([...window.comList])
  }

更改后,我们要在mainPart中,将这个属性传递给组件Com。
在mainPart下的index.tsx中:

    <div onDrop={onDrop} onDragOver={onDragOver} onDragEnter={onDragEnter} className='mainCom'>
      {
        comList.map(com => {
          const Com = components[com.comType as keyof typeof components];
          return <div key={com.comId} onClick={selectCom(com)} draggable onDragStart={onDragStart(com)}>
            <div className={com.comId === selectId ? 'selectCom' : ''} style={com.style}>
              // 直接通过结构,将属性传给Com
              <Com {...com}/>
            </div>
          </div>
        })
      }
    </div>

最后我们来到组件:

import { Button as AntButton } from 'antd'

export default function Button(props: any) {
  const {caption} = props
  return (
    <div>
      <AntButton>{caption || '按钮'}</AntButton>
    </div>
  )
}

拿到caption后,去渲染按钮的文字。

这里要注意的是,因为刚刚我把style属性提到了外层的div上,所以在组件这里,就不要再接受style了!!!!!!!!!!!!!!!!

OK,到这里,右侧的属性面板,就可以更改按钮的文字了。

在这里插入图片描述

本章内容会提交在github上:
https://github.com/TeacherXin/XinBuilder2
commit: 第四节:实现右侧属性面板

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

博主补充

本篇文章主要是为了帮助大家串通属性面板和组件之间的机制,主要还是清楚右侧改变的属性是如何映射到组件上的。

而在下一篇,我会主要实现右侧属性面板。比如,对于按钮来说,需要什么样的属性配置,对于Input框来说,需要什么样的属性配置。应该怎么去写代码,都会在下一章节继续完善。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

雄雄的小课堂微信机器人流程图

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 最近改造了下微信机器人&#xff0c;新版本还未上线&#xff0c;预计下周一&#xff08;12.25&#xff09;左右能上线第一版。 下面是改造之后的流程图 大家可以看看&#xff0c;有疑问可…

【万能技巧】IP知识速通与小技巧~

本文目录 前言一、网络代理IP简介二、IPIDEA 优势2.1 多种类型IP代理2.2 海量纯净代理池2.3 稳定高效数据收集架构 三、IP实操小Tips3.1 查看本地网络IP3.2 使用浏览器IP3.3 使用IPIDEA进行爬虫实操 前言 各位友友&#xff0c;大家好&#xff0c;马上就到2024年了&#xff0c;…

MyBatis 关联查询

目录 一、一对一查询&#xff08;sqlMapper配置文件&#xff09; 1、需求&#xff1a; 2、创建account和user实体类 3、创建AccountMapper 接口 4、创建并配置AccountMapper.xml 5、测试 二、一对多查询&#xff08;sqlMapper配置文件&#xff09; 1、需求&#xff1a;…

充电桩负载测试的影响是什么

充电桩负载测试是评估充电桩性能和稳定性的重要环节&#xff0c;其影响主要体现在以下几个方面&#xff1a; 1. 安全性&#xff1a;充电桩负载测试可以检测充电桩在高负载情况下的电气安全性能&#xff0c;如电压、电流、温度等参数是否在正常范围内。如果充电桩在高负载下出现…

【圣诞】极安云科赠书活动第①期:CTF实战:从入门到提升

【圣诞】极安云科赠书活动第①期&#xff1a;CTF实战:从入门到提升 9787111724834 9787121376955 9787302556275 ISBN编号&#xff1a;9787111724834 书名&#xff1a;CTF实战:从入门到提升 定&#xff1a;99.00元 开本&#xff1a;184&#xff4d;&#xff4d;260&#xff…

Android:安卓学习笔记之OkHttp原理的简单理解和使用

Android OkHttp使用原理的简单理解和使用 OkHttp 0、前言1、请求与响应流程 1.1 请求的封装1.2 请求的发送1.3 请求的调度1.4 请求的处理2、拦截器 2.1 RetryAndFollowUpInterceptor2.2 BridgeInterceptor2.3 CacheInterceptor 2.3.1、HTTP缓存原理2.3.2、强制缓存2.3.3、协商…

Linux网络编程(一):网络基础(下)

参考引用 UNIX 环境高级编程 (第3版)黑马程序员-Linux 网络编程 1. 协议的概念 1.1 什么是协议 从应用的角度出发&#xff0c;协议可理解为 “规则”&#xff0c;是数据传输和数据解释的规则 假设&#xff0c;A、B双方欲传输文件&#xff0c;规定&#xff1a; 第一次&#xff…

云闪付支付:一种新型的移动支付方式

随着科技的发展&#xff0c;我们的生活方式也在不断地改变。其中&#xff0c;移动支付已经成为我们生活中不可或缺的一部分。而在这个领域中&#xff0c;云闪付支付无疑是一种新型的、高效便捷的支付方式。那么&#xff0c;云闪付支付究竟是什么&#xff0c;它又有哪些特点呢&a…

2023年12月23日 十二生肖 今日运势

小运播报&#xff1a;2023年12月23日&#xff0c;星期六&#xff0c;农历十一月十一 &#xff08;癸卯年甲子月乙卯日&#xff09;&#xff0c;法定节假日。 红榜生肖&#xff1a;狗、猪、羊 需要注意&#xff1a;鼠、龙、鸡 喜神方位&#xff1a;西北方 财神方位&#xff…

Java 虚拟机中的内存结构

1 内存结构 1.1 程序计数器 1.1.1 定义 Program Counter Register 程序计数器&#xff08;寄存器&#xff09; 作用&#xff1a;是记住下一条 jvm 指令的执行地址 特点&#xff1a; 是线程私有的&#xff08;每个线程独有自己的一份&#xff09;不会存在内存溢出 1.1.2 作…

c# OpenCV 检测(斑点检测、边缘检测、轮廓检测)(五)

在C#中使用OpenCV进行图像处理时&#xff0c;可以使用不同的算法和函数来实现斑点检测、边缘检测和轮廓检测。 斑点检测边缘检测轮廓检测 一、斑点检测&#xff08;Blob&#xff09; 斑点检测是指在图像中找到明亮或暗的小区域&#xff08;通常表示为斑点&#xff09;&#…

设计模式:循序渐进走入工厂模式

文章目录 前言一、引入二、简单工厂模式1.实现2.优缺点3.扩展 三、工厂方法模式1.实现2.优缺点 四、抽象工厂模式1.实现2.优缺点3.使用场景 五、模式扩展六、JDK源码解析总结 前言 软件设计模式之工厂模式。 一、引入 需求&#xff1a;设计一个咖啡店点餐系统。 设计一个咖啡类…

java八股jvm

JVM虚拟机篇-01-JVM介绍、运行流程_哔哩哔哩_bilibili 1.PC程序计数器 2.堆 3.虚拟机栈 4.方法区/永久代/元空间 5.直接内存 JVM虚拟机篇-06-JVM组成-你听过直接内存吗_哔哩哔哩_bilibili 6.双亲委派 从下往上找&#xff0c;有同名类优先使用上级加载器的&#xff0c;不用自…

工作实践篇 Flink(一:flink提交jar)

一&#xff1a;参数 flink 模式 – standalone 二&#xff1a;步骤 1. 将本地测试好的代码进行本地运行。确保没问题&#xff0c;进行打包。 2. 找到打好的jar包&#xff0c;将jar包上传到对应的服务器。 3. 执行flink命令&#xff0c;跑代码。 /opt/flink/flink-1.13.6/bi…

Java中中文字典排序/多音字处理

Pinyin4j是一个Java库&#xff0c;用于将汉字转换为拼音。它是由中国清华大学的Tsinghua University和中国科学院计算技术研究所的研究人员开发的。Pinyin4j可以用于Java应用程序中&#xff0c;以便在需要时将汉字转换为拼音。例如&#xff0c;它可以用于中文输入法、文本编辑器…

Http---HTTP 请求报文

1. HTTP 请求报文介绍 HTTP最常见的请求报文有两种: GET 方式的请求报文POST 方式的请求报文 说明: GET: 获取web服务器数据POST: 向web服务器提交数据 2. HTTP GET 请求报文分析 HTTP GET 请求报文效果图: GET 请求报文说明: ---- 请求行 ---- GET / HTTP/1.1 # GET请…

慢调用链诊断利器-ARMS 代码热点

作者&#xff1a;铖朴、义泊 可观测技术背景 从最早的 Google 发表的一篇名为《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》的论文开始&#xff0c;到后来以&#xff1a;Metrics&#xff08;指标&#xff09;、Tracing&#xff08;链路追踪&#xf…

Android开发——添加图片

1、首先选择一张需要的图片&#xff0c;通过左侧的Resource Manage选择“”并选择Import Drawables 选择一张图片 并调整以下两个内容 这两个内容的作用借用谷歌官方的Android开发教程的内容&#xff1a; *Android 设备具有不同的屏幕尺寸&#xff08;手机、平板电脑和电视等…

2023 下半年系统架构设计师学习进度

文章目录 复习计划&#xff1a;每周350分钟第一周&#xff08;339分钟&#xff09;第二周&#xff08;265分钟&#xff09;第三周&#xff08;171分钟&#xff09;第四周&#xff08;214分钟&#xff09;第五周&#xff08;274分钟&#xff09;第六周&#xff08;191分钟&#…

医院手术麻醉系统源码,基于PHP、 js 、mysql、laravel、vue2技术开发,实现患者数据的自动采集和医疗文书自动生成

手麻系统作为医院信息化系统的一环&#xff0c;由监护设备数据采集系统和麻醉信息管理系统两个子部分组成。手麻信息系统覆盖了患者术前、术中、术后的手术过程&#xff0c;可以实现麻醉信息的电子化和手术麻醉全过程动态跟踪。 以服务围术期临床业务工作的开展为核心&#xf…