【Vue】如何写一个表格列显隐控制的组件?

需求

公司项目需要实现对表格列的显示隐藏进行配置,额外配置可自行添加,感觉这个组件挺泛用的,随便记录下。

这里只是说简单的显隐控制,复杂的只是在页面里面多写而已,核心代码是一样的。

简单的:

image

比较复杂的:

image

代码实现

表格页面.vue

<column-setup
@columnSetup="columnSetup"
:baseSelectedColumns="selectedColumns"
page="report"
></column-setup>
					
<el-table-column
prop="name"
label="Name"
width="auto"
v-if="isShowClumn('Name')"
show-overflow-tooltip
></el-table-column>
      selectedColumns: [
        {
          displayName: 'Name',
          show: true,
        },
        {
          displayName: 'Email Address',
          show: true,
        },
        {
          displayName: 'Profile Type',
          show: true,
        },
        {
          displayName: 'User Type',
          show: true,
        },
      ],
    columnSetup(selectedColumns) {
      this.selectedColumns = selectedColumns
    },
    isShowClumn(name) {
      let isShow
      this.selectedColumns.forEach((item) => {
        if (item.displayName === name) {
          isShow = item.show
        }
      })
      return isShow
    },

组件.vue

样式请自行删减,有些是无用代码。

点击查看代码
<template>
  <div class="table-custom-display">
    <el-tooltip effect="dark" content="Columns" placement="top">
      <el-popover
        placement="bottom"
        title=""
        trigger="click"
        v-model="visible"
        popper-class="columns-popover"
        @hide="close()"
        @show="show"
      >
        <h2>Columns</h2>
        <div class="top-check">
          <el-input
            placeholder="Search"
            prefix-icon="el-icon-search"
            v-model.trim="selectParam"
            clearable
            size="mini"
            @input="search"
          ></el-input>
          <div class="bot-check">
            <template v-for="(item, index) in selectedColumns">
              <div :key="item.name">
                <el-checkbox
                  v-model="item.show"
                  :key="item.name"
                  checked
                  v-show="isShowItem(item, index)"
                >
                  <div class="switch-defaults-name">
                    {{ item.displayName }}
                  </div>
                </el-checkbox>
              </div>
            </template>
          </div>
        </div>
        <div style="text-align: right; margin: 0" class="footer">
          <el-button type="primary" size="mini" @click="done">
            Done
          </el-button>
          <el-button size="mini" type="text" @click="visible = false">
            Cancel
          </el-button>
        </div>
        <el-button
          type=""
          size="medium"
          icon="el-icon-setting"
          style="font-size: 14px; margin-left: 10px; margin-top: 15px;"
          slot="reference"
        ></el-button>
      </el-popover>
    </el-tooltip>
  </div>
</template>

<script>
export default {
  name: '',
  props: {
    baseSelectedColumns: {
      type: Array,
      default: () => {
        return []
      },
    },
  },
  data() {
    return {
      buttons: sessionStorage.getItem('buttonPermissions'),
      visible: false,
      selectParam: '',
      matchIndexArr: [],
      initSelectedColumns:[],
      selectedColumns: [],
    }
  },
  watch: {
    baseSelectedColumns: {
      deep: true, // 深度监听
      handler(newVal, oldVal) {
        this.selectedColumns = JSON.parse(JSON.stringify(newVal))
      },
    },
  },
  mounted(){
    this.selectedColumns = JSON.parse(JSON.stringify(this.baseSelectedColumns))
  },
  methods: {
    close() {
      this.visible = false
    },
    show(){
      this.selectedColumns = JSON.parse(JSON.stringify(this.baseSelectedColumns))
    },
    done() {
      let content = JSON.parse(JSON.stringify(this.selectedColumns))
      this.visible = false
      this.$emit('columnSetup', content)
    },
    search() {
      this.matchIndexArr = []
      this.selectedColumns.forEach((item, index) => {
        let str = item.displayName.toLowerCase()
        if (str.match(this.selectParam) !== null) {
          this.matchIndexArr.push(index)
        }
      })
    },
    isShowItem(item, index) {
      if (this.selectParam) {
        return this.matchIndexArr.indexOf(index) !== -1
      } else {
        return true
      }
    },
  },
}
</script>

<style scoped lang="scss">
::v-deep .el-checkbox__input.is-checked + .el-checkbox__label {
  color: #596571 !important;
}

::v-deep .el-checkbox {
  display: flex;
  margin-right: 0;
}

::v-deep .el-checkbox__input,
.is-checked {
  display: flex;
  align-items: center;
}

::v-deep .el-checkbox__label {
  /* background-color: red; */
  width: 98%;
  height: 30px;
}

::v-deep .el-switch.is-checked .el-switch__core {
  border-color: #47bfaf !important;
  background-color: #47bfaf !important;
}

.top-check {
  // display: flex;
  // align-content: center;
  // justify-content: space-between;

  .reset {
    cursor: pointer;
    font-size: 14px;
  }

  /deep/.el-tabs__item {
    height: 28px;
    line-height: 28px;
    font-size: 18px;
    padding: 0 20px !important;
    color: #828282;
  }

  /deep/ .el-tabs__item:hover {
    color: #828282 !important;
  }

  /deep/ .el-tabs__item.is-active {
    color: #47bfaf !important;
  }

  /deep/ .el-input__inner {
    border: 1px solid #1e384b !important;
    color: #1e384b !important;
    border-radius: 5px;
    font-weight: 500;
    height: 35px;
  }

  /deep/ .el-icon-circle-close {
    color: #828282 !important;
    margin-left: -20px;
    line-height: 28px;
  }
}

.bot-check {
  margin-top: 10px;
  height: 170px;
  overflow-y: auto;

  /deep/.el-checkbox__label {
    padding: 5px 10px;
  }

  /deep/.el-link--inner {
    padding: 10px 0;
  }

  .check-box {
    display: flex;
    flex-direction: column;
  }

  .system-check-box {
    display: flex;
    justify-content: space-between;
  }

  .switch-defaults-name {
    max-width: 223px;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }

  .switch-system-name {
    max-width: 183px;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }

  .label-wrapper {
    margin: 14px 0;
    display: flex;

    &:nth-child(2) {
      margin-top: 0;
    }

    .label-item {
      display: flex;
      align-items: center;
    }

    .label-text {
      margin-left: 10px;
    }

    .label-switch {
      flex-grow: 1;
      justify-content: right;
    }
  }
}

.footer {
  /deep/ .el-button--primary {
    border-radius: 5px !important;
    background-color: #47bfaf;
    border-color: #47bfaf;
  }
}

.table-custom-display {
}
</style>
<style>
.columns-popover {
  background-color: #fff;
  width: 300px;
}

.icon-popover {
  background: #fff;
}

.columns-tootip {
  z-index: 200000000000020 !important;
}

.switch-tootip .popper__arrow {
  left: 40px !important;
}
</style>

posted @ 2022-05-23 14:10  努力挣钱的小鑫  阅读(204)  评论(0编辑  收藏  举报