Ant Design表格列拖拽,部分源码 #44

简介: Ant Design表格列拖拽,部分源码 #44

难点


  • 如何与现有的自定义列、拖拽功能保持兼容。
  • 如何与现有的代码和接口数据结构保持兼容。
  • 拖动列宽的时候,如何阻止拖拽事件发生。
  • 其他边缘情况。

源码


// 添加onmousedown事件和样式
const ResizeableTitle = (props) => {
    const { width, onMouseDown, index, ...restProps } = props;
    if(!width) {
        return <th {...restProps} />;
    }
    if(width.toString().indexOf('%') > -1) {
        return <th {...restProps} />;
    }
    const propsClassName = `${restProps.className} react-resizable-th`;
    const className = 'react-resizable';
    const key = `react-${index}`;
    // 通过cloneElement,添加span标签
    return React.cloneElement(
        <th {...restProps} />,
        {
            class: propsClassName,
        },
        [
            restProps.children,
            <span
                key={key}
                className={className}
                onMouseDown={onMouseDown}
                index={index}
                width={width}
                oldWidth={width}
            />
        ]
    );
};
this.newColums = (newColums) => {
    return newColums.map((col, index) => ({
        ...col,
        onHeaderCell: column => ({
            width: column.width,
            onMouseDown: this.onMouseDown,
            index
        }),
    }));
};
// 重新渲染列
components = {
    header: {
        cell: ResizeableTitle,
    },
};
// 获取列宽
getColumnWidth = (columnNames) => {
    const widths = [];
    if(document.getElementsByTagName('colgroup').length > 0) {
        const children = document.getElementsByTagName('colgroup')[0].children;
        if(children.length > 0) {
            for(let i = 0, len = children.length; i < len; i++) {
                if(children[i].className != 'ant-table-expand-icon-col') {
                    widths.push({
                        key: columnNames[i],
                        width: Number(children[i].style.width.match(/[0-9]+/)[0])
                    });
                }
            }
        }
    }
    document.onmousemove = null;
    document.onmouseup = null;
    return widths;
}
// 获取table宽度、当前点击列宽、鼠标x轴位置
onMouseDown = (e) => {
    e.stopPropagation();
    e.preventDefault();
    const table = document.getElementsByTagName('table');
    if(table.length === 0) {
        return;
    }
    if(!(table[0].getAttribute('style'))) {
        return;
    }
    const colgroup = document.getElementsByTagName('colgroup');
    if(colgroup.length === 0 || colgroup.length < 2) {
        return;
    }
    if(colgroup[0].children.length === 0) {
        return;
    }
    const target = e.target;
    const width = Number(target.getAttribute('width'));
    const oldWidth = Number(target.getAttribute('oldWidth'));
    const tableWidth = Number(table[0].getAttribute('style').match(/[0-9]+/));
    this.nativeEventX = e.nativeEvent.x;
    this.onMouseMove(table, colgroup, target, width, oldWidth, tableWidth);
    this.onMouseUp();
}
/**
 * @description 列宽拖动
 * @param table 表格
 * @param colgroup 表格
 * @param target 当前点击col
 * @param width col宽度        400px
 * @param oldWidth col宽度     400px 
 * @param tableWidth 表格宽度  400px
 * @memberof FilterWrap
 */
onMouseMove = (table, colgroup, target, width, oldWidth, tableWidth) => {
    document.onmousemove = (e) => {
        let index = Number(target.getAttribute('index'));
        // 展开行特殊处理
        if(colgroup[0].children[0].className === 'ant-table-expand-icon-col') {
            index++;
        }
        const col = colgroup[0].children[index];
        const col2 = colgroup[1].children[index];
        const currentX = (e.clientX) - this.nativeEventX;
        let newWidth;
        document.body.style.cursor = 'col-resize';
        newWidth = width + currentX;
        // 如果移动的距离小于原始宽度
        if(newWidth < oldWidth) {
            return;
        }
        // 负数转换正数
        if(newWidth < 0) {
            newWidth = -(newWidth);
        }
        const colWidth = `width: ${newWidth}px; min-width: ${newWidth}px`;
        const newTableWidth = `width: ${tableWidth + currentX}px;`;
        col.setAttribute('style', colWidth);
        col2.setAttribute('style', colWidth);
        table[0].setAttribute('style', newTableWidth);
        table[1].setAttribute('style', newTableWidth);
        target.setAttribute('width', `${newWidth}`);
    };
}
onMouseUp = () => {
    document.onmouseup = () => {
        // 拖动结束,进行保存
        document.body.style.cursor = 'default';
        document.onmousemove = null;
        document.onmouseup = null;
        let params = {};
        const { columns } = this.state;
        const { pageId, actions } = this.props;
        const postData = this.getDataIndex(columns);
        params.type = pageId;
        params.columnNames = postData;
        params.columnWidth = this.getColumnWidth(postData);
        // 发起接口存储列数据
        actions && actions.updateCustomList(params);
    };
}
目录
相关文章
|
存储 缓存 运维
【Docker 专栏】Docker 镜像的分层存储与缓存机制
【5月更文挑战第8天】Docker 镜像采用分层存储,减少空间占用并提升构建效率。每个镜像由多个层组成,共享基础层(如 Ubuntu)和应用层。缓存机制加速构建和运行,通过检查已有层来避免重复操作。有效管理缓存,如清理无用缓存和控制大小,可优化性能。分层和缓存带来资源高效利用、快速构建和灵活管理,但也面临缓存失效和层管理挑战。理解这一机制对开发者和运维至关重要。
914 8
【Docker 专栏】Docker 镜像的分层存储与缓存机制
|
前端开发
css特效——纯css绘制图标:带框的加号(添加按钮)、三横(三道杠)、带圈点(双层圆点)
css特效——纯css绘制图标:带框的加号(添加按钮)、三横(三道杠)、带圈点(双层圆点)
373 5
|
安全 定位技术 API
无代码平台评测:草料二维码
无代码平台让创建应用变得简单,无需编写代码,通过图形界面和预设模块,实现软件开发。草料二维码作为无代码平台,具备丰富功能,使用门槛低,适合一线业务人员和中小企业。其核心功能包括内容展示、表单、动态数据和批量生码,广泛应用于产品介绍、签到报名等场景。优点是搭建简单、使用方便且多数功能免费;缺点在于功能相对简单,不支持私有化部署。总体而言,它是实现低成本信息化管理的高性价比选择。
|
前端开发 Java Spring
`DeferredResult`用法简单介绍
`DeferredResult`用法简单介绍
316 1
|
缓存 Java
java使用MAT进行内存分析
java使用MAT进行内存分析
|
资源调度 前端开发
antd table表头拖拽实现(一)
antd table表头拖拽实现
1540 0
|
JavaScript 前端开发
vue3中使用jsx报错React is not defined和h is not defined
vue3中使用jsx报错React is not defined和h is not defined
1504 0
|
JavaScript jenkins 应用服务中间件
Jenkins + Github + Nginx 自动化部署 Vue 项目
Jenkins + Github + Nginx 自动化部署 Vue 项目
919 0
|
Dubbo Java 应用服务中间件
策略模式史上最佳实践,没有之一!!!
策略模式史上最佳实践,没有之一!!!
294 0
|
存储 缓存 前端开发
完美解决 - 前端发版后浏览器缓存问题(发版后及时拉取最新版本代码)
完美解决 - 前端发版后浏览器缓存问题(发版后及时拉取最新版本代码)
6165 0