最近在写一个东西,类似下面这张图,左边是组件区,比如有文本、图片、列表等;中间是渲染区,把左边的组件拖动到中间区域,就可以渲染一个对应的组件出来;鉴于每个组件需要不同的渲染结果,所以右边提供对每个组件的渲染内容的设置,根据每个组件类型的不同,右边编辑区的设置项也不同。
这个东西的使用场景是,让用户自定义页面,中间的渲染区是自定义页面的效果展示,组件区就是自定义页面上支持放置的组件。
用react来写,大体思路是这样:每个组件包含三个部分,分别是展示在左边的图标和文本说明,展示在中间的结果部分,展示在右边的设置部分,所有支持的组件放在一起,在用户自定义完毕保存后(数据格式可以用json等),下次渲染出的页面可以直接用组件的结果部分来渲染。
这里面的交互大概有这么些:
- 组件的拖动,从左边拖动组件到中间以创建一个新组件;中间区域已有组件的拖动以调整位置;从中间区域把已有组件拖出中间区域以删除;
- 组件的激活,创建组件时立即激活新创建的组件;已有的组件的点击,以切换和激活编辑
实际编写时遇到了如下问题:
- 拖动,使用原生的drag相关API在拖动过程中无法获取鼠标位置,所以使用了mouseup、mousedown、mousemove来模拟拖动
- 中间区域在实际渲染时用的是vue,所以起了一个iframe(这是下面一堆麻烦的源头),两个页面相互通信用postMessage,并且在iframe中无法获取到外部的鼠标事件,所以用一个div覆盖在iframe上面获取鼠标位置,react负责鼠标位置的发送、组件的编辑等,vue负责渲染组件、组件位置的获取和计算、通知react当前激活的组件信息等,因为iframe中的坐标和外部不一致,所以要做处理,而且还和iframe的布局位置关联(?)