演示地址
css
1. 先動態渲染表頭,給每個表頭添加一個class=virtual 的畫虛線的類名,同時給每一個表頭加上鼠標點擊、拖動、擡起事件:mousedown->mousemove->mouseup.html
2. 點擊時肯定點擊的哪一個,拖動的時候肯定拖動的方向,擡起的時候肯定放在的位置。vue
3. 改變數據實現拖動完成效果。element-ui
<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>