从零实现一套低代码(保姆级教程)【运行时】 --- 【30】实现组件的删除和复制功能

发布于:2024-07-05 ⋅ 阅读:(144) ⋅ 点赞:(0)

摘要

本篇主要来实现一下,在设计器里,对组件进行删除和复制的功能。这一篇不该在运行时的分组里面,但是写到这里来,就继续写下去吧。

因为在设计页面的时候,一定会出现拖拽错组件的情况。所以我们给设计器增加删除组件的功能,同时对于已经配置好的组件,如果想再配置出一个,不如直接复制来的爽快,所以我们再给组件加一个复制的功能。

至于这两个功能按钮,我们只需要一直在组件的正上方即可。

所以在
XinBuilder2/src/pages/builder/mainPart/index.tsx
修改我们的getComponent方法

  const getComponent = (com: any) => {
    const Com = components[com.comType as keyof typeof components];
    return <div>
        <div onDrop={onDropContainer(com)} key={com.comId} onClick={selectCom(com)}>
          <div draggable onDragStart={onDragStart(com)} style={com.style}>
            {selectId === com.comId && <div className='buttonList'>
              <CopyOutlined onClick={copyCom} />
              <DeleteOutlined onClick={deleteCom}/>
            </div>}
            <div className={com.comId === selectId ? 'selectCom' : ''}>
              <Com {...com} >
                {
                  com.childList && com.childList.map((item: any) => {
                    return getComponent(item)
                  })
                }
              </Com>
            </div>
          </div>
        </div>
      </div>
  }

只有选中某个组件的时候,组件的正上方会出现这两个按钮。
在方法里添加了这一段DOM结构。

{selectId === com.comId && <div className='buttonList'>
   <CopyOutlined onClick={copyCom} />
   <DeleteOutlined onClick={deleteCom}/>
 </div>}

在这里插入图片描述

1.实现组件删除的方法

现在我们实现deleteCom方法,因为我们有selectId知道当前选中的组件ID。所以我们只需要在comList中,将对应ID的组件删除掉,然后更新redux的comList即可。

  const deleteCom = () => {
    const list = comList.filter((item:ComJson) => {
      return item.comId !== selectId;
    })
    Store.dispatch({type: 'changeComList', value: list})
    message.success('删除成功');
  }

删除完之后再来一条提示即可。

2.实现组件复制的功能

删除的逻辑很简单,现在我们再实现一下复制组件的功能。由于我们要保存复制节点的组件信息,所以这里我们要使用state进行状态管理。同时复制的时候更新state。

  	const [copyNode, setCopyNode] = useState<ComJson>();
    const copyCom = () => {
    const copyNode = comList.find((item: ComJson) => {
      return item.comId === selectId;
    })
    setCopyNode(copyNode);
    message.success('复制成功,ctrl + v 或者 command + v 进行复制');
  }

但当我保存了复制组件的信息后,如何粘贴呢。我们希望的效果是,当我通过Ctrl + V 或者Command + V 后,在鼠标位置复制出来一个一模一样的组件。

所以我们需要监听鼠标的位置,并且再监听键盘的keydown事件,当满足条件后,我们在comList里添加copyNode,并且更新redux即可。

  let currentMousePosition = { x: 0, y: 0 };

  useEffect(() => {
    const copyFun = (e: any) => {
      const comList = JSON.parse(JSON.stringify(Store.getState().comList))
      if((e.ctrlKey || e.metaKey) && e.key === 'v') {
        const style = {
          position: 'absolute',
          left: currentMousePosition.x + 'px',
          top: currentMousePosition.y + 'px',
          zIndex:100
        }
        let comId = `comId_${Date.now()}`;
        const newNode = {...copyNode, comId, style};
        comList.push(newNode);
        Store.dispatch({type: 'changeComList', value: comList});
        setSelectId(comId);
      }
    }
    const mouseMove = (e: any) => {
      currentMousePosition.x = e.clientX;  
      currentMousePosition.y = e.clientY; 
    }
    document.addEventListener('mousemove', mouseMove);
    document.addEventListener('keydown', copyFun);
    return () => {
      document.removeEventListener('mousemove', mouseMove);
      document.removeEventListener('keydown', copyFun);
    }
  }, [copyNode])

在useEffect里,记得组件销毁的时候把绑定的事件销毁。直接return里进行document.removeEventListener操作。

这样,我们就完成了组件的复制和删除功能。

这部分代码提交在github上
https://github.com/TeacherXin/XinBuilder
commit: fix: 第二十五节:实现组件的删除和复制功能