仿表格简化版列表组件

当初某项目需要用到,但是都比较简单的列表展示,便临时写的,很久没再管过,功能比较简单

<template>
  <!-- 手写展示数据list -->
  <div class="be-table-list">
    <div class="be-table-ul" v-if="columnsNum <= 3 && columnsNum > 0">
      <ul class="be-table-header" v-if="isHeader">
        <li
          class="be-table-li be-head-item"
          :class="'be-item--' + columnsNum"
          v-for="headindex in columnsNum"
          :key="headindex"
        >
          <!-- 序号表头列 -->
          <div
            v-if="
              tableList.length > 0 && columns.length > 0 && tableIndex.isIndex
            "
            :style="
              cellHeight
                ? { width: tableIndex.width, height: cellHeight }
                : { width: tableIndex.width }
            "
            class="be-table-index cell"
          >
            序号
          </div>
          <!-- 所有表头列 -->
          <div
            class="cell cursor"
            v-for="item in tabColumns"
            :style="
              cellHeight
                ? {
                    height: cellHeight,
                    width: item.width,
                    flex: item.width ? 'none' : 1
                  }
                : { width: item.width, flex: item.width ? 'none' : 1 }
            "
            :key="item.prop"
            @click="sortTextClick(item.prop)"
          >
            {{ item.name || '' }}
            <span v-if="item.isSort" class="sort-icon">
              <i
                class="el-icon-caret-top"
                :class="
                  curSort.prop === item.prop && curSort.order === 'asc'
                    ? 'sort-icon-acitve'
                    : ''
                "
                @click="
                  (e) => {
                    sortClick(item.prop, 'asc', e)
                  }
                "
              ></i
              ><i
                class="el-icon-caret-bottom"
                :class="
                  curSort.prop === item.prop && curSort.order === 'desc'
                    ? 'sort-icon-acitve'
                    : ''
                "
                @click="
                  (e) => {
                    sortClick(item.prop, 'desc', e)
                  }
                "
              ></i
            ></span>
          </div>
          <!-- 操作列 -->
          <div
            class="be-table-oper cell"
            :style="
              cellHeight
                ? { width: tableOper.width, height: cellHeight }
                : { width: tableOper.width }
            "
            v-if="columns.length > 0 && tableOper.isOper"
          >
            {{ tableOper.headName }}
          </div>
        </li>
      </ul>
      <div
        :class="isHeader ? 'be-ishead-content' : 'be-nohead-content'"
        v-loading="loading"
        :element-loading-text="loadingText"
        :element-loading-spinner="loadingIcon"
      >
        <ul class="be-table-content">
          <li
            class="be-table-li be-list-item"
            v-for="(item, iindex) in tableList"
            :class="[
              { 'be-list--active': highlightCurrow && curRowIndex === iindex },
              'be-item--' + columnsNum,
              {
                'be-list--bgcolor':
                  stripe &&
                  ((columnsNum === 1 && iindex % 2 === 0) ||
                    (columnsNum === 2 &&
                      (iindex % 4 === 0 || iindex % 4 === 1)) ||
                    (columnsNum === 3 &&
                      (iindex % 6 === 0 ||
                        iindex % 6 === 1 ||
                        iindex % 6 === 2)))
              }
            ]"
            @click="rowClick(item, iindex)"
            @dblclick="doubleClick(item, iindex)"
            :key="item.id"
          >
            <!-- 序号列 -->
            <div
              v-if="
                tableList.length > 0 && columns.length > 0 && tableIndex.isIndex
              "
              :style="
                cellHeight
                  ? { width: tableIndex.width, minHeight: cellHeight }
                  : { width: tableIndex.width }
              "
              class="be-table-index cell"
            >
              {{ iindex + 1 }}
            </div>
            <!-- 所有字段列 -->
            <div
              class="cell"
              v-for="(value, vindex) in columns"
              :style="
                cellHeight
                  ? {
                      minHeight: cellHeight,
                      width: value.width,
                      flex: value.width ? 'none' : 1
                    }
                  : { width: value.width, flex: value.width ? 'none' : 1 }
              "
              :key="'value-' + vindex"
              @click="cellClick(value, vindex, item, iindex)"
            >
              <el-tooltip
                v-if="
                  value.tooltip &&
                  value.tooltip > 0 &&
                  item[value.prop]?.length > value.tooltip
                "
                :content="item[value.prop]"
                placement="top"
                :enterable="false"
                popper-class="list-tooltip"
                effect="light"
                ><span
                  >{{ item[value.prop].slice(0, value.tooltip) }}…</span
                ></el-tooltip
              >
              <span v-else>{{ item[value.prop] || '' }}</span>
            </div>
            <!-- 操作列,传参复杂 -->
            <div
              class="be-table-oper cell"
              :style="
                cellHeight
                  ? { width: tableOper.width, minHeight: cellHeight }
                  : { width: tableOper.width }
              "
              v-if="columns.length > 0 && tableOper.isOper"
            >
              <slot name="oper" v-bind="{ row: item, rowIndex: iindex }">
                <el-link
                  class="table-link"
                  v-for="(btn, index) in tableOper.linkList"
                  :key="index"
                  :type="btn.type || ''"
                  :disabled="btn.disabled ?? false"
                  :underline="btn.underline ?? tableOper.underline"
                  :icon="btn.icon || ''"
                  @click.stop="btnClick(btn.params, item)"
                  >{{ btn.text }}</el-link
                >
              </slot>
            </div>
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'BeautifulTableList',
  props: {
    // 加载loading
    loading: {
      type: Boolean,
      default: false
    },
    loadingText: {
      type: String,
      default: '数据加载中...'
    },
    loadingIcon: {
      type: String,
      default: 'el-icon-loading'
    },
    // 表头数量
    columnsNum: {
      type: Number,
      default: 1,
      validator: function (val) {
        return val <= 3 && val > 0
      }
    },
    // 是否斑马纹
    stripe: {
      type: Boolean,
      default: true
    },
    // 是否高亮当前行
    highlightCurrow: {
      type: Boolean,
      default: false
    },
    // 表格高度
    height: {
      type: String,
      default: '100%'
    },
    // cell高度,单位为rem
    cellHeight: String,
    // 序号内容
    indexObj: {
      type: Object,
      default() {
        return {}
      }
    },
    // 操作内容
    operObj: {
      type: Object,
      default() {
        return {}
      }
    },
    // 是否需要表头
    isHeader: {
      type: Boolean,
      default: true
    },
    // 表格数据
    dataList: {
      type: Array,
      required: true,
      default() {
        return []
      }
    },
    // 表头数据
    columns: {
      type: Array,
      required: true,
      default() {
        return []
      }
    },
    // 默认点击的数据索引
    defaultRowIndex: Number
  },
  data() {
    return {
      curRowIndex: null,
      // 所有数据
      tableList: [],
      // 当前排序的信息
      curSort: {
        prop: '',
        order: ''
      }
    }
  },
  computed: {
    // 定义默认序号列数据
    tableIndex() {
      return Object.assign(
        {
          isIndex: false,
          width: '3.75rem'
        },
        this.indexObj
      )
    },
    // 表头排序
    tabColumns() {
      const col = this.$utils.compareSort(this.columns, 'key')
      return col
    },
    // 定义默认操作列数据
    // 默认每个按钮都有各自的属性,如果属性不存在,则查看是否存在公共的
    // operButton集合字段:type(类型), text(文本), click(点击), underline(下划线), icon(图标)
    // isOper是否需要操作列,isUnifiedOper是否统一操作列,否则自定义,headName表头名称
    tableOper() {
      return Object.assign(
        {
          operButton: [],
          isOper: false,
          isUnifiedOper: true,
          btnUnderline: false,
          headName: '操作',
          width: '6.25rem'
        },
        this.operObj
      )
    }
  },
  watch: {
    // 监听数据改变,清空当前点击项
    dataList: {
      handler() {
        const list = this._cloneDeep(this.dataList)
        if (this.curSort.prop) {
          this.tableList = this.$utils.compareSort(
            list,
            this.curSort.prop,
            this.curSort.order
          )
        } else {
          this.tableList = list
        }
        this.curRowIndex =
          this.defaultRowIndex === undefined ? null : this.defaultRowIndex
      },
      deep: true,
      immediate: true
    }
  },
  beforeDestroy() {
    this.curSort = {
      prop: '',
      order: ''
    }
    this.tableList = []
  },
  methods: {
    // 行点击
    rowClick(row, rowIndex) {
      this.$emit('rowClick', { row, rowIndex })
    },
    // 双击列表
    doubleClick(row) {
      this.$emit('doubleClick', { row })
    },
    // 单元格点击,四个参数,单元格信息,单元格索引,行信息,行索引
    cellClick(cell, cellIndex, row, rowIndex) {
      this.curRowIndex = rowIndex
      this.$emit('cellClick', { cell, cellIndex, row, rowIndex })
    },
    // 排序的点击
    sortClick(prop, order, e) {
      if (e) {
        e.stopPropagation()
      }
      if (this.curSort.prop === prop && this.curSort.order === order) {
        // 如果点击的是同一个字段和同样顺序,则取消排序
        this.tableList = this._cloneDeep(this.dataList)
        this.curSort.prop = ''
        this.curSort.order = ''
      } else {
        // 如果不是则排序
        this.curSort.prop = prop
        this.curSort.order = order
        this.tableList = this.$utils.compareSort(this.tableList, prop, order)
      }
    },
    sortTextClick(prop) {
      const { order } = this.curSort
      if (!order) {
        this.sortClick(prop, 'asc')
      } else if (order === 'asc') {
        this.sortClick(prop, 'desc')
      } else if (order === 'desc') {
        this.curSort.prop = ''
        this.curSort.order = ''
        this.tableList = this.dataList
      }
    }
  }
}
</script>

<style scoped lang="less">
.cursor {
  cursor: pointer;
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值