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