天天看點

element-ui table 拖拽實作

Element-Ui Table 元件原本是不支援拖拽的,由于實際開發過程中有拖拽功能的需求,從開發角度上來說這種使用第三方元件庫不支援然後自己加功能的方式有 Hack 的嫌疑,稍有不慎,代碼就會越寫越爛,日積月累導緻項目爆炸💥,變得難以維護,如同破窗效應。

Table 支援拖拽功能

vuedraggable

是一個拖拽類元件,底層是他們的

Sortable

庫,有老外對此封裝了一個 NPM Package,根據實際情況取舍是 copy 一個檔案還是 install 一個包。

使用下面的代碼作為一個元件引入,

handle

指定具體的 DOM 元素可拖拽,用于防止

input

無法滑鼠選中的情況。

<template>
  <div ref="wrapper">
    <div :key="tableKey">
      <slot />
    </div>
  </div>
</template>

<script>
import sortable from 'sortablejs'
export default {
  name: 'ElementUiElTableDraggable',
  props: {
    handle: {
      type: String,
      default: ''
    },
    animate: {
      type: Number,
      default: 100
    }
  },
  data () {
    return {
      tableKey: 0
    }
  },
  watch: {
    tableKey () {
      this.$nextTick(() => {
        this.makeTableSortAble()
        this.keepWrapperHeight(false)
      })
    }
  },
  mounted () {
    this.makeTableSortAble()
  },
  methods: {
    makeTableSortAble () {
      const table = this.$children[0].$el.querySelector(
        '.el-table__body-wrapper tbody'
      )
      sortable.create(table, {
        handle: this.handle,
        animation: this.animate,
        onEnd: ({ newIndex, oldIndex }) => {
          this.keepWrapperHeight(true)
          this.tableKey = Math.random()
          const arr = this.$children[0].data
          const targetRow = arr.splice(oldIndex, 1)[0]
          arr.splice(newIndex, 0, targetRow)
          this.$emit('drop', { targetObject: targetRow, list: arr })
        }
      })
    },
    keepWrapperHeight (keep) {
      // eslint-disable-next-line prefer-destructuring
      const wrapper = this.$refs.wrapper
      if (keep) {
        wrapper.style.minHeight = `${wrapper.clientHeight}px`
      } else {
        wrapper.style.minHeight = 'auto'
      }
    }
  }
}
</script>           

複制

el-form-item 拖拽

watch: {
  uuid () {
    this.$nextTick(() => {
      this.makeTableSortAble()
      this.keepWrapperHeight(false)
    })
  }
},
mounted () {
  this.makeTableSortAble()
}



makeTableSortAble () {
  const table = document.querySelector(
    '.edit-nested-drag'
  )
  sortable.create(table, {
    handle: '.el-form-item__label',
    animation: 100,
    onEnd: ({ newIndex, oldIndex }) => {
      this.keepWrapperHeight(true)
      this.uuid = Math.random()
      const targetRow = this.config.tabList.splice(oldIndex, 1)[0]
      this.config.tabList.splice(newIndex, 0, targetRow)
      // this.$emit('drop', { targetObject: targetRow, list: this.config.tabList })
    }
  })
},
keepWrapperHeight (keep) {
  // eslint-disable-next-line prefer-destructuring
  const wrapper = document.querySelector(
    '.edit-nested-drag'
  )
  if (keep) {
    wrapper.style.minHeight = `${wrapper.clientHeight}px`
  } else {
    wrapper.style.minHeight = 'auto'
  }
}           

複制