領導說你這個element的table過於枯燥乏味,已經知足不了我了,給我加幾個功能吧

拖拽打印等功能javascript

功能概述

  • 我要表頭能拖拽排序
  • 我要表頭能自定義顯示隱藏
  • 我要調整好表格能打印
  • 每一項我均可能要加排序,是後臺排序

你安排我我就作唄

效果展現

思路分析

拖拽

拖拽大概有兩種(onmousemove,ondrag),簡單的具體思路都是,記錄下開始點,再獲取到結束點,交換完事css

表頭自定義

在表頭右邊加個自定義下拉按鈕html

打印

打印瀏覽器不是有麼,調用print()就能夠,打印表格估計就是把表格這塊摳出來,弄到個新文檔,打印vue

排序

是後臺排序,那我就只要監聽個事件回調,調後臺就能夠了java

參考

因爲老衲過於菜雞,保守起見,仍是先來查查別人是怎麼弄的吧git

參考(fuzhi)地址github

拖拽chrome

打印瀏覽器

實現

打印
  • 扣出須要打印的區域innerHTML到新建的一個iframe頁面裏面
  • 獲取到樣式懟進去
  • print()打印
<template>
    <div>
        <div ref="template">
            <slot>
            </slot>
        </div>
        <button v-if="buttonShow" @click="print" type="button" :class="buttonClass">
            <span>開始打印</span>
        </button>
    </div>
</template>
複製代碼
export default {
  props: {
    // 是否顯示默認的打印按鈕
    buttonShow: {
      type: Boolean,
      default: false
    },
    buttonClass: {
      type: String,
      default: 'el-button el-button--default'
    }
  },
  mounted () {
    this.init()
  },
  methods: {
    init () {
      let printI = document.getElementById('easyPrintIframe')
      if (!printI) {
        printI = document.createElement('iframe')
        printI.id = 'easyPrintIframe'
        printI.style.position = 'fixed'
        printI.style.width = '0'
        printI.style.height = '0'
        printI.style.top = '-100px'
        // 兼容ie
        if (
          window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)
        ) {
          printI.src = 'javascript:document.write("<head><script>document.domain="' + document.domain + '";</s' + 'cript></head><body></body>")'
        }
        printI.onload = () => {
          this.getStyle()
        }
        document.body.appendChild(printI)
      } else {
        this.getStyle()
      }
    },
    print () {
      if (typeof this.beforeCopy === 'function') {
        // 檢測到有複製前須要執行的功能
        this.beforeCopy()
      }
      let $iframe = document.getElementById('easyPrintIframe')
      // 複製body,打印內容
      $iframe.contentDocument.body.innerHTML = this.$refs.template.innerHTML
      if (typeof this.beforePrint === 'function') {
        // 檢測到有打印前須要執行的功能
        // 好比有些二維碼組件沒法直接複製dom完成。
        this.beforePrint()
      }
      setTimeout(() => {
        $iframe.contentWindow.print()
      }, 100)
    },
    getStyle () {
      let mystyle = ``
      let printI = document.getElementById('easyPrintIframe')
      var str = ''
      var styles1 = document.querySelectorAll('style')
      for (var i = 0; i < styles1.length; i++) {
        str += styles1[i].outerHTML
      }
      // console.log(str)
      printI.contentDocument.head.innerHTML = str + mystyle
      // 添加link引入
      let styles = document.querySelectorAll('link')
      for (let i = 0; i < styles.length; i++) {
        // chrome 正常,firefox不正常,能執行到,可是添加沒結果
        let link = document.createElement('link')
        link.setAttribute('rel', 'stylesheet')
        if (styles[i].type) link.setAttribute('type', styles[i].type)
        else link.setAttribute('type', 'text/css')
        link.setAttribute('href', styles[i].href)
        link.setAttribute('media', 'all')
        printI.contentDocument.head.appendChild(link)
      }
    }
  }
}

複製代碼
表頭操做拖拽排序
  • 表頭元素都添加handleMouseMove事件,移動過程當中,移到別的列上,交換位置
<template>
  <div>
    <div class="w-table" :class="{'w-table_moving': dragState.dragging}">
        <div class="edit">
            <el-dropdown type="primary" size="small" trigger="click">
              <span class="el-dropdown-link">
                <i class="el-icon-edit"></i>
              </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item v-for="(item, index) in tableHeaderBackup" :key="index">
                  <div>
                    <el-checkbox v-model="item.show" @change="init">{{item.label}}</el-checkbox>
                  </div>
                </el-dropdown-item>
                <el-dropdown-item style="padding:10px 15px 8px;">
                  <el-button @click="print" type="primary" style="width:100%;" icon="el-icon-download" size="small">打印</el-button>
                </el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
        </div>
      
        <easy-print ref="print">
        <el-table ref="table" row-key="id" :data="tableData" :header-cell-class-name="headerCellClassName" :cell-class-name="cellClassName" :style="`width: 100%`" >

          <template v-for="(col, index) in tableHeaderYes ">
            <el-table-column v-if="col.show" :key="index" :prop="col.prop" :label="col.label" :width="col.width" :min-width="col.minWidth" :type="col.type" :header-align="col.headerAlign" :column-key="index.toString()" :render-header="renderHeader" >
            <template slot-scope="scope" >
              <div v-if="col.format" v-html="col.format(scope.row[col.prop])"></div>
              <div v-else>{{scope.row[col.prop]}}</div>
            </template>
            </el-table-column>
          </template>
        </el-table>
        </easy-print>
    </div>
  </div>
</template>
複製代碼
export default {
    data () {
        return {
          dragState: {
            start: -9, // 起始元素的 index
            end: -9, // 移動鼠標時所覆蓋的元素 index
            dragging: false, // 是否正在拖動
          },
          tableHeaderBackup: [], //備份完整的tableHeader
          tableHeaderYes: [],// 須要在表頭顯示的
          tableHeaderNo: [], // 暫時不顯示的
          tableHeader: [
            {
                prop: 'name',
                label: '油站名稱',
                show: true,
                minWidth: '120'
            },
            {
              prop: 'address',
              label: '油站地址',
              sort: 1,
              show: true,
              minWidth: '120'
            },
            {
              prop: 'header',
              label: '油站負責人',
              sort: 1,
              show: true,
              minWidth: '120'
            },
            {
              prop: 'headerPhone',
              label: '負責人電話',
              sort: 1,
              show: true,
              minWidth: '120'
            },
            {
              prop: 'updateTime',
              label: '更新時間',
              sort: 1,
              show: true,
              minWidth: '120'
            }
          ],
          tableData: []
        }
    },
    mounted () {
        this.tableHeaderBackup = this.$tool._deepCopy(this.tableHeader)
        this.init()
    },
    methods: {
        init () {
            this.tableHeaderYes = this.tableHeaderBackup.filter(i => i.show)
            this.tableHeaderNo = this.tableHeaderBackup.filter(i => !i.show)
        },
        renderHeader (createElement, { column, $index }) {
          return createElement(
            'div',
            {
              class: ['thead-cell-box'],
              on: {
                mousedown: $event => {},
                mousemove: $event => {}
              }
            },
            [
              createElement(
                'span',
                {
                  class: ['thead-cell1']
                },
                column.label
              ),
              createElement('span', {
                class: ['thead-cell'],
                on: {
                  mousedown: $event => {
                    this.handleMouseDown($event, column)
                  },
                  mousemove: $event => {
                    this.handleMouseMove($event, column)
                  }
                }
              }),
              createElement(
                'span',
                {
                  class: {
                    'thead-cell2': true,
                    'caret-wrapper': true,
                    hidden: !this.tableHeaderYes[$index].sort,
                    ascending: this.tableHeaderYes[$index].sort === 2,
                    descending: this.tableHeaderYes[$index].sort === 3
                  },
                  on: {
                    click: $evnet => {
                      this.clickHandler($evnet, column, $index)
                    }
                  }
                },
                [
                  createElement(
                    'i',
                    {
                      class: ['sort-caret', 'ascending']
                    }
                  ),
                  createElement(
                    'i',
                    {
                      class: ['sort-caret', 'descending']
                    }
                  )
                ]
              )
            ]
          )
        },
        handleMouseDown (e, column) {
          this.dragState.dragging = true
          this.dragState.start = parseInt(column.columnKey)
          document.addEventListener('mouseup', this.handleMouseUp)
        },
    
        handleMouseUp () {
            // 初始化拖動狀態
          this.dragState.start = -9
          this.dragState.end = -9
          this.dragState.dragging = false
          document.removeEventListener('mouseup', this.handleMouseUp)
        },
    
        handleMouseMove (e, column) {
          if (this.dragState.dragging) {
            let index = parseInt(column.columnKey) // 記錄起始列
            if (index - this.dragState.start !== 0) {
                this.dragState.end = parseInt(column.columnKey)
                this.dragColumn(this.dragState) // 換位置
            }
          } else {
            return false
          }
        },
    
        dragColumn ({ start, end, direction }) {
          const tableHeaderYes = this.$tool._deepCopy(this.tableHeaderYes)
    
            //交換位置
            const startObj = tableHeaderYes[start]
            this.tableHeaderYes.splice(start, 1)
            this.tableHeaderYes.splice(end, 0, startObj)
          
            this.tableHeaderBackup = this.tableHeaderYes.concat(this.tableHeaderNo)//合併從新設置表頭
            this.dragState.dragging = false
            this.$nextTick(() => {
              this.dragState.dragging = true
              this.dragState.start = end
              this.dragState.end = start
            })
          
    
        },
    
        // 拖拽樣式的設置
        headerCellClassName ({ column, columnIndex }) {
          if (this.showSelection) columnIndex--
          if (this.showExpand) columnIndex--
          let active =
            columnIndex === this.dragState.end
              ? `darg_active_${this.dragState.direction}`
              : ''
          let start = columnIndex === this.dragState.start ? `darg_start` : ''
          return `${active} ${start}`
        },
        cellClassName ({ column, columnIndex }) {
          if (this.showSelection) columnIndex--
          if (this.showExpand) columnIndex--
          return columnIndex === this.dragState.start ? `darg_start` : ''
        },
        
        //打印包住區域
        print () {
            this.$refs.print.print()
        },
        
        // 點擊表頭排序回調事件 1是默認,2升序,3降序
        clickHandler (e, c, i) {
            this.tableHeaderYes.map((item, index) => {
                if (i === index) {
                  item.sort++
                  if (item.sort >= 4) {
                    item.sort = 1
                  }
                } else if (item.sort) {
                  item.sort = 1
                }
            })
            
            console.log(c.property, this.tableHeaderYes[i].sort)// 字段名,排序狀態
            
        }
    }
}


複製代碼
.w-table {
  position: relative;
  .edit {
    position: absolute;
    right: 0;
    top: 0;
    z-index: 10;
    .el-dropdown-link {
      cursor: pointer;
      background: #fff;
      color: #1890ff;
      font-size: 20px;
      border: 1px solid #dfe6ec;
      box-sizing: border-box;
      height: 40px;
      width: 40px;
      display: flex;
      justify-items: center;
      align-content: center;
    }

    i {
      margin: 0;
      width: 40px;
      text-align: center;
      line-height: 40px;
    }
  }
  .cell {
    transition: all ease 0.2s;
  }
  .el-table {
    thead {
      th{
        transition: all ease 0.2s;
      &:hover{
          background: #ddd;
        }
    }
      .cell{
        line-height: 40px;

      }
      .darg_start {
        background: #999 !important;
        cursor: move;
        .cell{
          color: #fff;
        }
      }
    }
  }
  .el-table th {
    padding: 0;
    .thead-cell-box {
        display: block;
        position: relative;
        white-space: normal;
    }
  .thead-cell {
    cursor:copy;
    position: absolute;
    top: 0;
    left: -10px;
    bottom: 0;
    right: 0;
  }
  .thead-cell2 {
    width: 35px;
  }
  .thead-cell1 {
    display: inline-block;
    position: relative;
    white-space: normal;
    font-weight: 800;
    line-height: 22px;
  }
  &.w-table_moving {
    .el-table th .thead-cell {
      cursor: move !important;
    }
    .el-table__fixed {
      cursor: not-allowed;
    }
  }
}

複製代碼

搞完收工,200到手,下班下班,明天再來封裝成組件app

轉載記錄地址連接

相關文章
相關標籤/搜索