1. 程式人生 > 程式設計 >基於el-table封裝的可拖拽行列、選擇列元件的實現

基於el-table封裝的可拖拽行列、選擇列元件的實現

效果

基於el-table封裝的可拖拽行列、選擇列元件的實現

需要環境


elementUI
拖拽外掛Sortable.

需配置屬性

基於el-table封裝的可拖拽行列、選擇列元件的實現

示例

<HTawww.cppcns.comble
  :columns="columns"
  :data="list"
  :setColumn="true"
  tableKey="CategoriesList"
  style="width: 100%"
  border
>
http://www.cppcns.com  // 這裡可以放插槽
  <template slot="create_time" slot-scope="scope">
    {{ scope.column.label + scope.item.prop }}
  </template>
  <template slot="action" slot-scope="scope">
    <el-button type="primary" @click="handleEdit(scope.row)" size="small">
      編輯
    &l
t;/el-button> <el-button @click="handleDelete(scope.row)" type="danger" size="small"> 刪除 </el-button> </template> </HTable> import HTable from "@/components/HTable"; export default { components: { HTable },data() { return { list: [],columns: [ { label: "ID",// 描述 prop: "_id",// 列的唯一值。 必須要有 checked: true // 是否展示該列 ... // 一些el-table-column的屬性都可以寫在這裡 },{ label: "分類名稱",prop: "name",checked: true },{ label: "上級分類",prop: "parent.name",{ label: "狀態",prop: "status",width: "100",{ label: "建立時間",prop: "create_time",slotHeaderName: "create_time",// 自定義表頭 checked: true },{ label: "操作",prop: "action",fixed: "right","min-width": "100",slotName: "action",// 自定義單元格插槽 checked: true,disabled: true } ] }; } };

有用到的話給我點個贊!附元件程式碼

<template>
  <div class="HTable">
    <div class="settingBox" v-if="setColumn">
      <el-popover
        placement="bottom-end"
        trigger="click"
        popper-class="settingPopper"
      >
        <el-checkbox-group
          v-model="selectCol"
          @change="handleChangeSelectColumn"
        >
          <el-checkbox
            v-for="item in col"
            :key="item.prop"
            :label="item.prop"
            :disabled="item.disabled"
            style="display:block;line-height:2;margin-right:0;"
            >{{ item.label }}</el-checkbox
          >
        </el-checkbox-group>
        <i class="icon el-icon-setting" slot="reference"></i>
      </el-popover>
    </div>
    <el-table
      v-bind="$attrs"
      :data="tableData"
      v-on="$listeners"
      :key="JSON.stringify(checkedCol)"
    >
      <el-table-column
        v-for="(item,index) in checkedCol"
        :key="item.prop"
        v-bind="item"
        :index="index"
        :column-key="item.prop"
      >
        <template v-if="item.slotHeaderName" v-slot:header="scope">
          <slot :name="item.slotHeaderName" v-bind="scope" :item="item"></slot>
        </template>
        <template v-if="item.slotName" v-slot:default="scope">
          <slot :name="item.slotName" v-bind="scope"></slot>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import Sortable from "sortablejs";
export default {
  name: "HTable",props: {
    tableKey: String,columns: {
      type: Array,default() {
        return [];
      }
    },data: {
      type: Array,setColumn: {
      type: Boolean,default: false
    }
  },watch: {
    columns: {
      handler(newVal) {
        let localVal = this.getStorageCol();
        let hotVal = [];
        if (localVal) {
          hotVal = this.dataDiff(newVal,localVal);
        } else {
          hotVal = [...newVal];
        }
        this.col = hotVal.map(
          (item,index) =>
            (item = { ...item,index,checked: item.checked || false })
        );
        this.checkedCol = this.checkedColFun(this.col);
        this.selectCol = this.checkedCol.map(item => (item = item.prop));
      },immediate: true
    },data: {
      handler(newVal) {
        this.tableData = [...newVal];
      },col: {
      handler(newVal) {
        this.setStorageCol(newVal);
      },deep: true,immediate: true
    }
  },data() {
    return {
      tableData: [],col: [],checkedCol: [],selectCol: []
    };
  },mounted() {
    document.body.ondrop = function(event) {
      event.preventDefault();
      event.stopPropagation();
    };
    this.$nextTick(() => {
      this.rowDrop();
      this.columnDrop();
    });
  },methods: {
    drap() {
      this.$nextTick(() => {
        this.rowDrop();
        this.columnDrop();
      });
    },handleChangeSelectColumn() {
      this.col.forEach(item => {
        if (this.selectCol.includes(item.prop)) {
          item.checked = true;
        } else {
          item.checked = false;
        }
      });
      this.checkedCol = this.checkedColFun(this.col);
      this.drap();
    },rowDrop() {
      const tbody = document.querySelector(".el-table__body-wrapper tbody");
      Sortable.create(tbody,{
        onEnd: ({ newIndex,oldIndex }) => {
          [this.tableData[newIndex],this.tableData[oldIndex]] = [
            this.tableData[oldIndex],this.tableData[newIndex]
          ];
          this.drap();
          this.$emit("dropRow",{
            drapRow: this.tableData[oldIndex],targetRow: this.tableData[newIndex],drapRowIndex: oldIndex,targetRowIndex: newIndex,data: this.tableData
          });
        }
      });
    },columnDrop() {
      const wrapperTr = document.querySelector(".el-table__header-wrapper tr");
      Sortable.create(wrapperTr,{
        animation: 180,delay: 0,onEnd: ({ newIndex,oldIndex }) => {
          const oldItem = this.checkedCol[oldIndex];
          const newItem = this.checkedCol[newIndex];
    wRDnPTjQWW
[this.col[newItem.index].index,this.col[oldItem.index].index] = [ oldItem.index,newItem.index ]; this.col.sort((a,b) => { return a.index - b.index; }); this.checkedCol = this.checkedColFun(this.col); this.tableData = this.tableData.slice(0,this.tableData.length); this.drap(); this.$emit("dropCol",{ colItem: oldItem,newIndex: newIndex,oldIndex: oldIndex,column: this.checkedCol }); } }); },checkedColFun(arr) { return arr.filter(item => item.checked); },setStorageCol(data) { if (this.tableKey && data && data.length > 0) { localStorage.setItem("HTable-" + this.tableKey,JSON.stringify(data)); } },getStorageCol() { let datajson = localStorage.getItem("HTable-" + this.tableKey); return datajson ? JSON.parse(datajson) : ""; },dataDiff(newVal,localVal) { let nl = newVal.length; let ll = localVal.length; if (nl != ll) { return newVal; } else { let np = newVal.map(item => item.prop).sort(); let lp = localVal.map(item => item.prop).sort(); if (np.join() != lp.join()) { return newVal; } else { let nnl = []; for (let i = 0; i < localVal.length; i++) { const item_l = localVal[i]; for (let j = 0; j < newVal.length; j++) { const item_n = newVal[j]; if (item_l.prop === item_n.prop) { nnl.push({ ...item_n,index: item_l.index }); } } } return nnl; } } } } }; </script> <style lang="less" scoped> .HTable { position: relative; .settingBox { width: 36px; height: 36px; border-radius: 2px; border: 1px solid #ebeef5; border-bottom: 0; margin-left: auto; position: relative; .icon { position: absolute; top: 0; left: 0; z-index: 1; width: 36px; height: 36px; text-align: center; font-size: 20px; line-height: 36px; color: #909399; cursor: pointer; } } } </style&www.cppcns.comgt; <style lang="less"> .settingPopper { min-width: 100px !important; } </style>

到此這篇關於基於el-table封裝的可拖拽行列、選擇列元件的實現的文章就介紹到這了,更多相關el-table 可拖拽行列內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!