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)和应用层。缓存机制加速构建和运行,通过检查已有层来避免重复操作。有效管理缓存,如清理无用缓存和控制大小,可优化性能。分层和缓存带来资源高效利用、快速构建和灵活管理,但也面临缓存失效和层管理挑战。理解这一机制对开发者和运维至关重要。
1171 8
【Docker 专栏】Docker 镜像的分层存储与缓存机制
|
存储 移动开发 关系型数据库
HarmonyOS 鸿蒙面试第一弹
HarmonyOS 鸿蒙面试第一弹
|
安全 定位技术 API
无代码平台评测:草料二维码
无代码平台让创建应用变得简单,无需编写代码,通过图形界面和预设模块,实现软件开发。草料二维码作为无代码平台,具备丰富功能,使用门槛低,适合一线业务人员和中小企业。其核心功能包括内容展示、表单、动态数据和批量生码,广泛应用于产品介绍、签到报名等场景。优点是搭建简单、使用方便且多数功能免费;缺点在于功能相对简单,不支持私有化部署。总体而言,它是实现低成本信息化管理的高性价比选择。
|
存储 安全 Java
阿里二面,面试官:说说 Java CAS 原理?
阿里二面,面试官:说说 Java CAS 原理?
阿里二面,面试官:说说 Java CAS 原理?
|
缓存 Java
java使用MAT进行内存分析
java使用MAT进行内存分析
|
存储 算法 关系型数据库
TDengine 3.3.0.0 发布:图形化管理工具、复合主键等10+ 功能更新
在涛思数据研发团队的努力下,TDengine 3.3.0.0 版本终于和大家见面了。这一版本中,我们引入了多项革新功能和性能优化,力求在为用户提供极致体验的同时,不断推动技术的前沿。
421 0
|
Linux Windows
10. 【Linux教程】cd 路径操作
10. 【Linux教程】cd 路径操作
500 0
|
JSON 数据库 数据格式
gorm 教程三 gen自动代码生成工具
gorm 教程三 gen自动代码生成工具
1308 0