zoukankan      html  css  js  c++  java
  • element-ui 实现table整列的拖动

    演示地址

    1. 先动态渲染表头,给每一个表头添加一个class=virtual 的画虚线的类名,同时给每个表头加上鼠标点击、拖动、抬起事件:mousedown->mousemove->mouseup.

    2. 点击时确定点击的哪个,拖动的时候确定拖动的方向,抬起的时候确定放在的位置。

    3. 改变数据实现拖动完成效果。

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>自定义表头样式和整列的拖动</title>
        <link rel="stylesheet" href="https://unpkg.com/element-ui@2.3.7/lib/theme-chalk/index.css">
        <script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
        <script src="https://unpkg.com/element-ui@2.3.7/lib/index.js"></script>
        <style>
            *{
                padding:0;
                margin:0;
            }
            body {
                padding:50px;
                overflow-x: hidden;
            }
            .thead-cell{
                position: relative;
            }
            .drag_table th {
                cursor: move;
            }
            .virtual {
                position: fixed;
                display: block;
                margin-top: -35px;
                margin-left: -11px; 
            }
            .drag_active_left .virtual {
                border-left: 1px dotted #666;
                z-index: 99;
            }
            .drag_active_right .virtual {
                border-right: 1px dotted #666;
                z-index: 99;
            }
            /* 
                给选中要拖动的列添加背景色,如果在完整项目内部的组件,所以这个组件的style,不能加scoped,否则添加不上样式
                如果使用了sass或者less,可以加scoped 然后在用特殊手法处理样式
            */
            .dragging_column {
                background-color: #f3f3f3 !important;
            }
            
        </style>
    </head>
    
    <body>
        <div id="app">
                <p style="text-align:center;font-size:20px;margin-bottom:50px;">自定义表头样式和整列的拖动</p>
                <div @mouseleave="moveTableOutside">
                    <el-table class="drag_table" :data="tableData" border stripe :cell-class-name="cellClassName" :header-cell-class-name="headerCellClassName">
                        <el-table-column v-for="(col, index) in tableHeader" :key="index" :prop="col.prop" :label="col.label" :column-key="index.toString()" :render-header="renderHeader">
                        </el-table-column>
                    </el-table>
                </div>
            </div>
    </body>
    <script>
        var Main = {
            data() {
                return {
                    tableData: [{
                        name: '王小虎',
                        date: '2016-05-02',
                        address: '上海市普陀区金沙江路 1518 弄'
                    }, {
                        name: '王老五',
                        date: '2016-05-04',
                        address: '上海市普陀区金沙江路 1517 弄'
                    }, {
                        name: '王大锤',
                        date: '2016-05-01',
                        address: '上海市普陀区金沙江路 1519 弄'
                    }, {
                        name: '王小龙',
                        date: '2016-05-03',
                        address: '上海市普陀区金沙江路 1516 弄'
                    }],
                    tableHeader: [{
                        prop: 'name',
                        label: '姓名'
                    }, {
                        prop: 'date',
                        label: '时间'
                    }, {
                        prop: 'address',
                        label: '地址'
                    }],
                    dragState: {
                        startIndex: -1, // 拖动起始元素的index
                        endIndex: -1, // 拖动结束元素的index
                        afterMoveIndex: -1, // 拖动后元素的index
                        dragging: false, // 是否正在拖动
                        direction: null, // 拖动方向
                        moveTableOutsideBack: false // 拖出到table外之后又拖回来
                    }
                }
            },
            methods: {
                // drag_table在渲染表头时调用
                renderHeader(h, {
                    column,
                    $index
                }) {
                    // 这里可以根据$index的值来对自身需求进行修改,
                    return h('span', {
                        'class': ['thead-cell'],
                        style: {
                            'display': 'block',
                            'width': '100%',
                            'cursor': 'move',
                        },
                        on: {
                            mousedown: ($event) => {
                                this.handleMouseDown($event, column)
                            },
                            mouseup: ($event) => {
                                this.handleMouseUp($event, column)
                            },
                            mousemove: ($event) => {
                                this.handleMouseMove($event, column)
                            }
                        }
                    }, [
                        h('span', [
                            // 给每个表头添加icon 可以不需要
                            h('span', {
                                class: $index === 0 ? 'el-icon-star-off' : $index === 1 ? 'el-icon-time' : $index === 2 ? 'el-icon-location' : '',
                            }),
                            h('span', column.label)
                        ]),
                        // 给每个表头添加一个class=virtual 是画虚线的类名。
                        h('span', {
                            'class': ['virtual']
                        })
                    ])
                },
                // 按下鼠标开始拖动 设置列的背景色
                handleMouseDown(e, column) {
                    // 判断是鼠标左键
                    if (e.button === 0) {
                        this.dragState.dragging = true
                        this.dragState.startIndex = parseInt(column.columnKey)
                        console.log(`开始移动的位置 ${this.dragState.startIndex}`)
                        // 给当前要拖动列的th设置class
                        document.querySelectorAll('.drag_table table thead tr th')[this.dragState.startIndex].className += ' ' + 'dragging_column';
                        // 给拖动时的虚拟容器添加宽高                    
                        let table = document.getElementsByClassName('drag_table')[0]
                        let virtual = document.getElementsByClassName('virtual')
                        // 设置新插入的span.virtual的标签 每一列的宽度、高度
                        for (let item of virtual) {
                            item.style.height = table.clientHeight - 1 + 'px'
                            item.style.width = item.parentElement.parentElement.clientWidth + 'px'
                        }
                        this.dragState.moveTableOutsideBack = false
                    }
                },
                // 拖动中
                handleMouseMove(e, column) {
                    // 判断是鼠标左键
                    if (e.button === 0) {
                        if (this.dragState.dragging) {
                            let currentIndex = parseInt(column.columnKey) // 拖动的当前列index
                            console.log(`移动到了${currentIndex}`)
                            if (currentIndex !== this.dragState.startIndex) {
                                this.dragState.direction = currentIndex - this.dragState.startIndex < 0 ? 'left' : 'right' // 判断拖动方向
                                this.dragState.afterMoveIndex = currentIndex
                            } else {
                                this.dragState.direction = null
                            }
                        } else {
                            return false
                        }
                    }
                },
                // 鼠标放开结束拖动
                handleMouseUp(e, column) {
                    // 判断是鼠标左键
                    if (e.button === 0) {
                        // 拖出当前table外之后又拖回来,不再进行易位操作(拖出去时已处理)
                        if (this.dragState.moveTableOutsideBack) {
                            return false
                        } else {
                            this.dragState.endIndex = parseInt(column.columnKey) // 记录结束列index
                            console.log(`结束移动的位置 ${this.dragState.endIndex}`)
                            if (this.dragState.startIndex !== this.dragState.endIndex) {
                                this.dragColumn(this.dragState)
                            }
                            this.finishDragInit()
                        }
                    }
                },
                // 拖动到当前table之外的处理
                moveTableOutside() {
                    if (this.dragState.dragging) {
                        this.dragState.endIndex = this.dragState.startIndex
                        console.log(`已移动到table外,结束移动的位置 ${this.dragState.endIndex}`)
                        if (this.dragState.startIndex !== this.dragState.endIndex) {
                            this.dragColumn(this.dragState)
                        }
                        this.finishDragInit()
                        this.dragState.moveTableOutsideBack = true
                    }
                },
                // 拖动易位
                dragColumn({
                    startIndex,
                    endIndex,
                    direction
                }) {
                    console.log(`从${startIndex}移动到了${endIndex}`)
                    // 排除掉鼠标点击table外面,然后拖入进table报错
                    if (startIndex < 0) {
                        return;
                    }
                    // 判断是向左移动还是向右移动
                    // 把移动的列插在某个列前面或者后面,然后在删除移动的列
                    if (direction === 'left') {
                        this.tableHeader.splice(endIndex, 0, this.tableHeader[startIndex])
                        this.tableHeader.splice(startIndex + 1, 1)
                    } else {
                        this.tableHeader.splice(endIndex + 1, 0, this.tableHeader[startIndex])
                        this.tableHeader.splice(startIndex, 1)
                    }
                },
                // 拖动完成后的初始化
                finishDragInit() {
                    // 给当前要拖动列的th取消class
                    for (var item of document.querySelectorAll('.drag_table table thead tr th')) {
                        item.className = String(item.className).split("dragging_column").join("");
                    }
                    // 再次初始化拖动状态
                    this.dragState = {
                        startIndex: -1,
                        endIndex: -1,
                        afterMoveIndex: -1,
                        dragging: false,
                        direction: null,
                        moveTableOutsideBack: false
                    }
                },
                // 动态给表头单元格添加 class,实现拖动中的虚线效果
                /* 
                    这个监听在table渲染的时候会执行一遍。 
                    然后还会有两个条件会触发执行:
                    1. 绑定的数据发生变化的时候(即为表格内容变化就触发)。header变化触发header-cell-class-name,表格数据变化触发cell-class-name.
                    2. return返回值 如果绑定了data,如果此data变化也会触发执行。相当于对这个data进行了监听随之触发这个方法。
                */
                headerCellClassName({
                    column,
                    columnIndex
                }) {
                    console.log(1111111)
                    return columnIndex === this.dragState.afterMoveIndex ? `drag_active_${this.dragState.direction}` : ''
                },
                // 动态给表头单元格th添加class,实现拖动中的背景
                cellClassName({
                    column,
                    columnIndex
                }) {
                    console.log(22222)
                    return (columnIndex === this.dragState.startIndex ? `dragging_column` : '')
                },
            },
            mounted() {
                var that = this;
                setTimeout(function() {
                    //  that.tableHeader[0].label = 'wwwwww';
                    //  that.tableData[0].name = 'wwwwww';
                    //  console.log()
                    // console.log(document.querySelectorAll('.drag_table .el-table_2_column_4')[0])
                    // document.querySelectorAll('.drag_table table thead tr th')[0].className += ' ' + 'dragging_column';
                    // that.dragState.startIndex = '1'
                }, 5000)
            }
        }
        var Ctor = Vue.extend(Main)
        new Ctor().$mount('#app')
    </script>
    
    </html>
  • 相关阅读:
    252个基本词根详解
    记忆宫殿|一个故事轻松记忆常见252个英语字根(190~252)
    海外旅游最常用的100句英语口语
    与老外见面的10大经典句
    ReportManager
    ContextLoader
    Workflow License invalid!!
    JD-GUI
    DJ Java Decompiler
    AndroChef Java Decompile
  • 原文地址:https://www.cnblogs.com/wangmaoling/p/10525048.html
Copyright © 2011-2022 走看看