美文网首页
element 表格拖拽排序与动态表头

element 表格拖拽排序与动态表头

作者: 二两毛豆 | 来源:发表于2022-09-20 11:22 被阅读0次

    解决表头过多(20+)表格数据展示不直观的问题。

    产品功能

    1.隐藏不重要的表头
    2.表头拖拽排序
    3.可设置默认显示n个表头
    4.自定义设置不可关闭的表头

    实现效果

    image.png

    实现代码

    为了对组件的解耦故对组件进行了拆分

    主页面
    <template>
      <div class="sc">
        <sctable :productList="productList" :defaultColumns="defaultColumns">
          <headerBtn
            slot="customizeBtn"
            :defaultColumns="defaultColumns"
            @customizeHeader="(val) => (defaultColumns = val)"
          ></headerBtn>
        </sctable>
      </div>
    </template>
    <script>
    export default {
      components: {
        headerBtn: require("./module/headerBtn.vue").default,
        sctable: require("./module/table.vue").default,
      },
      props: {},
      data() {
        return {
          productList: [
            {
              productNo: "产品编号",
              customerProductNo: "客户产品编号",
              name: "笔记本",
              englishName: "macBook",
              productLabel: "产品标签",
              logisticsLabel: "物流标签",
              productClassify: "产品分类",
              salesman: "销售",
              buyer: "采购",
              tradeMode: "贸易方式",
            }
          ],
          //编辑后的表头
          defaultColumns: [
            { label: "中文名称", prop: "name" },
            { label: "英文名称", prop: "englishName" },
            { label: "产品编号", prop: "productNo" },
            { label: "客户产品编号", prop: "customerProductNo" },
            { label: "产品标签", prop: "productLabel" },
            { label: "物流标签", prop: "logisticsLabel" },
            { label: "产品分类", prop: "productClassify" },
            { label: "销售", prop: "salesman" },
            { label: "采购", prop: "buyer" },
            { label: "贸易方式", prop: "tradeMode" },
          ],
        };
      },
    };
    </script>
    
    <style lang="scss" scoped>
    .sc /deep/ {
      width: 1200px;
      height: 800px;
      background: #dcdfe6;
      margin: 20px auto;
      padding: 50px 10px;
      .set_row {
        text-align: right;
        margin: 10px 0;
      }
    }
    </style>
    
    拖拽与动态显示(核心功能)
    <template>
      <div class="customize_btn">
        <el-popover
          placement="bottom-end"
          popper-class="del_popover"
          title="表头显示"
          width="500"
          trigger="click"
          v-model="visible"
        >
          <el-divider content-position="center">拖拽排序</el-divider>
          <div class="tag_show">
            <ul class="tag_ul">
              <li
                class="tag_li"
                :key="tag.label"
                v-for="(tag, index) in beFacedHeader"
                draggable
                @dragenter="dragenter($event, index)"
                @dragover="dragover($event, index)"
                @dragstart="dragstart(index)"
              >
                {{ tag.label }}
                <i
                  @click="handleClose(tag)"
                  v-if="notDeleteArr.indexOf(tag.prop) == -1 ? true : false"
                  class="el-icon-close"
                ></i>
              </li>
            </ul>
          </div>
          <el-divider v-if="newDefaultColumns.length" content-position="center"
            >选至上方显示,选至下方不显示</el-divider
          >
          <div v-if="newDefaultColumns.length" class="tag_show">
            <ul class="tag_ul">
              <li
                class="tag_li"
                :key="index"
                v-for="(tag, index) in newDefaultColumns"
              >
                {{ tag.label }}
                <i
                  @click="handleCloseNew(tag)"
                  v-if="notDeleteArr.indexOf(tag.prop) == -1 ? true : false"
                  class="el-icon-close"
                ></i>
              </li>
            </ul>
          </div>
    
          <div style="overflow: hidden; margin: 0 5px" v-if="!isLiveUpdate">
            <div style="float: left; margin: 0; display: inline-block">
              <el-button
                class="search_txt_btn"
                size="mini"
                type="text"
                @click="reset"
                >重置</el-button
              >
            </div>
            <div style="float: right; margin: 0; display: inline-block">
              <el-button
                class="search_txt_btn"
                size="mini"
                type="text"
                @click="visible = false"
                >取消</el-button
              >
              <el-button
                class="tile_btn"
                type="primary"
                size="mini"
                @click="visible = false"
                >确定</el-button
              >
            </div>
          </div>
    
          <div slot="reference" class="set_row">
            <el-button class="set_btn" plain icon="el-icon-setting"
              >列表设置</el-button
            >
          </div>
        </el-popover>
      </div>
    </template>
      
      <script>
    export default {
      props: {
        // 是否实时更新
        isLiveUpdate: {
          type: Boolean,
          default: true,
        },
        // 不可被关闭的收起的数组
        notDeleteArr: {
          type: Array,
          default: () => ["productNo", "name"],
        },
        // 默认显示前5个表头
        defaultHeaderLength: {
          type: Number,
          default: 5,
        },
        //   表头
        defaultColumns: {
          type: Array,
          default: () => [],
        },
      },
      data() {
        return {
          dragIndex: "", //当前拖拽的元素下标
          visible: false,//浮窗状态
          beFacedHeader: [],// 显示的表头集合
          newDefaultColumns: [],//隐藏的表头集合
        };
      },
      created() {
        this.beFacedHeader = JSON.parse(JSON.stringify(this.defaultColumns));
        // 默认只显示前 'defaultHeaderLength' 个表头
        let arr1 = this.beFacedHeader.slice(0, this.defaultHeaderLength);
        let arr2 = this.beFacedHeader.slice(
          this.defaultHeaderLength,
          this.beFacedHeader.length
        );
        this.beFacedHeader = arr1;
        this.newDefaultColumns = arr2;
        this.$emit("customizeHeader", this.beFacedHeader);
      },
      mounted() {},
      methods: {
        dragstart(index) {
          this.dragIndex = index;
        },
        dragover(e, index) {
          e.preventDefault();
        },
        dragenter(e, index) {
          e.preventDefault();
          // 避免源对象触发自身的dragenter事件
          if (this.dragIndex !== index) {
            const source = this.beFacedHeader[this.dragIndex];
            this.beFacedHeader.splice(this.dragIndex, 1);
            this.beFacedHeader.splice(index, 0, source);
            // 排序变化后目标对象的索引变成源对象的索引
            this.dragIndex = index;
            this.$emit("customizeHeader", this.beFacedHeader);
          }
        },
        // 显示的表头
        handleClose(tag) {
          this.beFacedHeader.splice(this.beFacedHeader.indexOf(tag), 1);
          let newDefaultColumns = this.newDefaultColumns;
          newDefaultColumns.push(tag);
          this.newDefaultColumns = newDefaultColumns;
          this.$emit("customizeHeader", this.beFacedHeader);
        },
        // 隐藏的表头
        handleCloseNew(tag) {
          this.newDefaultColumns.splice(this.newDefaultColumns.indexOf(tag), 1);
          let beFacedHeader = this.beFacedHeader;
          beFacedHeader.push(tag);
          this.beFacedHeader = beFacedHeader;
          this.$emit("customizeHeader", this.beFacedHeader);
        },
      },
    };
    </script>
      
    <style lang="scss" scoped>
    .customize_btn {
      .set_btn {
        background: #fff;
        color: #000;
        border: 1px solid #dcdfe6;
      }
      .set_btn:hover,
      .set_btn:focus {
        background: #fff;
        color: #000;
        border: 1px solid #dcdfe6;
      }
    }
    .tag_ul {
      list-style: none;
      padding: 0;
      .tag_li {
        display: inline-block;
        font-size: 12px;
        background-color: #f4f4f5;
        border-color: #e9e9eb;
        color: #909399;
        margin: 3px 5px;
        height: 24px;
        padding: 0 8px;
        line-height: 22px;
        border-radius: 4px;
        border-width: 1px;
        border-style: solid;
        border-radius: 4px;
        box-sizing: border-box;
        white-space: nowrap;
        .el-icon-close {
          color: #909399;
          border-radius: 50%;
          text-align: center;
          position: relative;
          cursor: pointer;
          font-size: 12px;
          height: 16px;
          width: 16px;
          line-height: 16px;
          vertical-align: middle;
          top: 0px;
          right: -5px;
          transform: scale(0.8);
        }
        .el-icon-close:hover {
          color: #fff;
          background-color: #909399;
        }
      }
    }
    </style>
    
    表格
    <template>
      <div class="sc_table">
        <slot name="customizeBtn"></slot>
        <el-table
          ref="table"
          :data="productList"
          style="width: 100%"
          highlight-current-row
          class="primor_table_input table_sty"
          :header-cell-style="header_style"
          :row-style="tableRowStyle"
        >
          <el-table-column type="selection" fixed="left"></el-table-column>
          <el-table-column
            v-for="(item, index) in defaultColumns"
            :key="index"
            show-overflow-tooltip
            :prop="item.prop"
            :label="item.label"
            :width="item.width"
            :min-width="item.minWidth ? item.minWidth : '120'"
          >
            <template slot-scope="scope">
              {{ scope.row[item.prop] }}
            </template>
          </el-table-column>
        </el-table>
      </div>
    </template>
      
      <script>
    export default {
      props: {
        //   数据源
        productList: {
          type: Array,
          default: () => [],
        },
        //   表头
        defaultColumns: {
          type: Array,
          default: () => [],
        },
      },
    };
    </script>
    

    相关文章

      网友评论

          本文标题:element 表格拖拽排序与动态表头

          本文链接:https://www.haomeiwen.com/subject/rxomortx.html