目前,我们还有最后一个小模块没有实现,那就是左侧的数据。
我们希望它能够展示整个页面的相关协议,其实也就是我们redux中管理的数据。我们希望能够通过可视化的方式看到它。
因为有时候我们想知道一个组件的具体信息,就可以通过这种方式去查看。
同时在之前的篇章中,我们实现的容器组件是嵌套关系的,所以这里展示数据的组件,我们选择使用Tree组件。
如果你是第一次看到这一篇文章, 建议先看一下第一节内容:
从零实现一套低代码(保姆级教程) — 【1】初始化项目,实现左侧组件列表
OK,现在我们实现左侧的组件层级树。
首先,我们应该拿到redux中保存的comList组件列表,它是一个多层的嵌套数组,为了初始化层级树的数据,我们要递归将其转换为Tree组件需要的结构。
const items: TabsProps['items'] = [
{
key: 'component',
label: <div style={{fontSize:'18px',width:'100px',textAlign:'center'}}>组件</div>,
children: <Collapse className='comCollapse' items={collapseItems} defaultActiveKey={'enterDataCom'}/>,
},
// 层级树返回的组件
{
key: 'data',
label: <div style={{fontSize:'18px',width:'100px',textAlign:'center'}}>数据</div>,
children: getTreeList(),
}
];
const getTreeList = () => {
const comList = Store.getState().comList;
const toTreeData = (arr: []) => {
return arr.map((item: any) => {
const node: any = {
title: item.caption,
key: item.comId,
}
if(item.childList) {
node.children = toTreeData(item.childList)
}
return node
})
}
const treeData = [{
title: '组件协议',
key: 'zujianxieyi',
children: toTreeData(comList)
}]
console.log(treeData);
return <Tree
className='leftList'
showLine={true}
treeData={treeData}
/>
}
OK。我们用组件的caption作为标题,comId作为key,来渲染整个层级树。
同时,如果redux的数据更新了,我们的层级树也需要更新,所以这里我们也要引入subscribeHook方法
现在,我们可以看到整颗树了,但是有一个问题,树上啥也没有,这是为啥呢?
这是因为,我们创建每个节点的时候,并没有给每个组件caption属性,所以这里我们要给所有的组件进行初始化caption。
这里我就直接简单一点,通过一个递增的num来表示了,大家有好方法自己去改进,我这里就不管重不重名了。
回到mainPart下,我们修改一下onDrop方法:
const onDrop = (e: any) => {
// 其他代码
const comNode = {
comType: nowCom,
style,
comId,
// 初始话caption
caption: componentTextMap[nowCom] + num++
}
// 其他代码
}
对于所有组件,那也一定要能修改caption,所以我们把没有caption属性的组件给加上。
对于后面读者自己新增的组件,也一定要把caption属性给加上。
现在我们的树结构就很清晰了。
有了层级树之后,我希望能够右键点击查看协议。OK,我们先来实现右键的点击功能,我们要先修改getTreeList方法,我们的每个节点不能只是一段文本了。
然后我们要有一个弹窗来展示组件的json,那我们就要管理这个弹窗的显示和隐藏
我们要有一个状态用来表示展示哪个组件
const [showJson, setShowJson] = useState(false)
const [jsonComId, setJsonComId] = useState('')
const dropItems = [
{
label: '查看JSON',
key: 'showJson'
}
]
const menuOnClick = (comId: string) =>{
return (menuItem: any) => {
if(menuItem.key === 'showJson'){
// 展示协议的弹窗
setShowJson(true)
setJsonComId(comId)
}
}
}
const getTreeList = () => {
const comList = Store.getState().comList;
const toTreeData = (arr: []) => {
return arr.map((item: any) => {
const node: any = {
// 修改节点的title
title: <div>
<Dropdown menu={{onClick: menuOnClick(item.comId), items: dropItems }} trigger={['contextMenu']}>
<span>{item.caption}</span>
</Dropdown>
</div>,
key: item.comId,
}
if(item.childList) {
node.children = toTreeData(item.childList)
}
return node
})
}
}
OK,现在我们只需要实现弹窗即可。
我们在modal文件夹下新增一个弹窗:
这个弹窗里,我们只需要拿到查看节点的comId,然后给它的JSON展示出来即可。
import { Modal, Typography } from 'antd'
import Store from '../../../store';
import { getComById } from '../../../utils/nodeUtils';
const { Paragraph } = Typography;
export default function EditJson(props) {
const {showJson, setShowJson, jsonComId} = props
const comList = JSON.parse(JSON.stringify(Store.getState().comList))
const selectNode = getComById(jsonComId, comList)
return (
<Modal
open={showJson}
onOk={() => {setShowJson(false)}}
onCancel={() => {setShowJson(false)}}
closable={false}
>
<Paragraph
style={{
maxWidth: 440,
marginTop: 24,
}}
>
<pre
style={{
border: 'none',
height:'370px',
width:'450px',
overflow:'auto'
}}
>
{JSON.stringify(selectNode, null, 2)}
</pre>
</Paragraph>
</Modal>
)
}
现在我们就可以通过右键查看JSON了。
到此,左侧的层级树,大致就实现了。
相关的代码提交在github上:
https://github.com/TeacherXin/XinBuilder2
commit: 第十二节: 实现左侧层级树并支持查看JSON