摘要
本篇主要来实现一下,在设计器里,对组件进行删除和复制的功能。这一篇不该在运行时的分组里面,但是写到这里来,就继续写下去吧。
因为在设计页面的时候,一定会出现拖拽错组件的情况。所以我们给设计器增加删除组件的功能,同时对于已经配置好的组件,如果想再配置出一个,不如直接复制来的爽快,所以我们再给组件加一个复制的功能。
至于这两个功能按钮,我们只需要一直在组件的正上方即可。
所以在
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: 第二十五节:实现组件的删除和复制功能