<
>

基于el-table封装的可拖拽行列、选择列组件的实现

2022-04-16 06:04:42 来源:易采站长站 作者:

效果

基于el-table封装的可拖拽行列、选择列组件的实现

需要环境

vue
elementUI
拖拽插件Sortable.js

需配置属性

基于el-table封装的可拖拽行列、选择列组件的实现

示例

<HTable  :columns="columns"  :data="list"  :setColumn="true"  tableKey="CategoriesList"  style="width: 100%"  border>  // 这里可以放插槽  <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">      编辑    </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",          checked: true        },        {          label: "状态",          prop: "status",          width: "100",          checked: true        },        {          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,      default() {        return [];      }    },    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];      },      immediate: true    },    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,        : center;      font-size: 20px;      line-height: 36px;      color: #909399;      cursor: pointer;    }  }}</style><style lang="less">.settingPopper {  min-width: 100px !important;}</style>

暂时禁止评论

微信扫一扫

易采站长站微信账号