主要功能
- 拖拽实现组件嵌套. (组件套娃)
关键技术点
- HTML5 draggable
- webApi Drag https://developer.mozilla.org/zh-CN/docs/Web/API/Document/drag_event
- react-dom 在指定dom节点插入dom组件
核心代码
import React, {useContext, useEffect, useRef} from 'react';
import {Button} from 'antd';
import {BasicContext} from './index';
import styles from './index.less';
import {initConfig, getTitleList, getConfigComponent} from './utils';
import ReactDOM from 'react-dom';
const titleList = getTitleList();
export default function ButtonList() {
const {setTitle, title, setConfig} = useContext(BasicContext);
let draggedDom = useRef();
function setComponent(e) {
const titleThis = e.currentTarget.dataset.title;
// console.log(titleThis);
setTitle(titleThis);
setConfig(initConfig(titleThis));
}
useEffect(() => {
/* 拖动目标元素时触发drag事件 */
document.addEventListener("drag", function (event) {
}, false);
document.addEventListener("dragstart", function (event) {
// 保存拖动元素的引用(ref.)
draggedDom.current = event.target;
// 使其半透明
// event.target.style.opacity = 0.5;
}, false);
document.addEventListener("dragend", function (event) {
// 重置透明度
// event.target.style.opacity = "";
}, false);
/* 放置目标元素时触发事件 */
document.addEventListener("dragover", function (event) {
// 阻止默认动作以启用drop
event.preventDefault();
}, false);
document.addEventListener("drop", function (event) {
// 阻止默认动作(如打开一些元素的链接)
event.preventDefault();
// 将拖动的元素到所选择的放置目标节点中
if (event.target.className.indexOf('index-grid') === -1) {
return true; // 区域外部 不能拖拽。
}
const titleThis = draggedDom.current.dataset.title;
console.log(titleThis);
const config = initConfig(titleThis);
const componentProps = config.componentProps; // 通过配置项获取 配置的props
const Component = getConfigComponent(config.Component); // 通过配置项获取 配置的组件
const DomThis = <Component componentProps={componentProps}/>;
ReactDOM.render(DomThis, event.target);
}, false);
}, [])
return <div className={styles.buttonList}>
{
titleList.map((x) => {
return (
<Button onClick={setComponent} type={'danger'}
data-title={x}
key={x}
draggable={true}
>
{x}
</Button>
)
})
}
<h2>{title}</h2>
<h4 style={{color: 'red'}}>
点击按钮进行切换, 拖拽按钮实现 布局嵌套
</h4>
</div>
}