vue3 简单封装element-plus table

77 阅读1分钟

html部分:

<template>
  <el-table :style="{ width: '100%' }" :header-cell-style="{ fontSize: '14px', background: '#cdecdf  !important' }"
    v-bind="$attrs" v-loading="loading" ref="tableRef" :data="tableData" :max-height="maxHeight" :row-key="rowKey"
    :highlight-current-row="highlightCurrentRow" @row-click="handleRowClick" @select-all="selectAll"
    @selection-change="handleSelectionChange" stripe>
    <el-table-column v-for="item in columns" v-bind="$attrs" :key="item.prop"
      :align="item.align ? item.align : 'center'" :prop="item.prop" :label="item.label"
      :show-overflow-tooltip="item.showOverflowTooltip || true" :width="item.width" :fixed="item.fixed"
      :type="item.type" :sortable="item.sortable" :selectable="item.selectableFn">
      <!-- type 对应列的类型。 如果设置了selection则显示多选框; -->
      <!-- 如果设置了 index 则显示该行的索引(从 1 开始计算); -->
      <!-- 如果设置了 expand 则显示为一个可展开的按钮-->
      <!-- selection / index / expand -->
      <!-- 加斜线 -->
      <template #header v-if="item.names && item.names.length > 0">
        <div class="right">{{ item.names[0] }}</div>
        <div class="left">
          {{ item.names[1] }}
        </div>
      </template>
      <template #header v-else-if="item.headerTitle">
        <!-- {{ item.headerTitle }} -->
        <slot :name="item.headerTitle">

        </slot>
      </template>
      <template #default="{ row, column, $index }" v-if="item.type === 'index'">
        {{ $index + 1 + (getIndex || 0) }}
      </template>
      <!-- 内容 -->
      <template #default="{ row, column, $index }" v-if="item.function">
        <div v-html="item.function(row)"></div>
      </template>
      <template #default="{ row, $index, column }" v-else="!item.type">
        <!-- 具名作用域插槽 -->
        <slot :name="item.prop" :slotProps="row" :index="$index" :column="column">
          <!-- 默认内容,当父组件不传内容时默认显示该内容 -->
          <span v-if="item.formatter">
            {{ item.formatter(row[item.prop]) }}
          </span>
          <span v-else>
            {{ row[item.prop] || "/" }}
          </span>
        </slot>
      </template>
    </el-table-column>
  </el-table>
</template>

js部分

<script setup>
import { nextTick, toRefs, watch } from "vue";
const props = defineProps({
  // 表格相关
  tableData: {
    type: Array,
    default: [],
  },
  columns: {
    type: Array,
    default: [],
  },
  maxHeight: {
    type: String,
    default: "600px",
  },
  stripe: {
    type: Boolean,
    default: false,
  },
  rowKey: {
    type: String,
    default: "id",
  },
  highlightCurrentRow: {
    type: Boolean,
    default: true,
  },
  loading: {
    type: Boolean,
    default: false,
  },
  queryParams: {
    type: Object,
    default: () => ({})
  }
});

let {
  tableData,
  columns,
  height,
  maxHeight,
  stripe,
  rowKey,
  highlightCurrentRow,
  loading,
  arr,
} = toRefs(props);
const tableRef = ref(null);
const emit = defineEmits([
  "rowClick",
  "selectChange",
  "changeTableData",
  "update:pageSize",
  "select-all",
]);
// 默认勾选
const toggleRowSelections = (rows) => {
  nextTick(() => {
    rows.forEach((row) => {
      if (tableRef.value) {
        tableRef.value.toggleRowSelection(row, true);
      }
    });
  });
};
// 单行选中
const setCurrent = (row) => {
  nextTick(() => {
    if (tableRef.value) {
      tableRef.value.setCurrentRow(row)
    }
  });
}


// 清除所有选中
const clearSelection = () => {
  tableRef.value.clearSelection();
};
// 当某一行被点击时会触发该事件
const handleRowClick = (row, column, event) => {
  emit("rowClick", { row, column, event });
};
// 当选择项发生变化时会触发该事件
const handleSelectionChange = (selection) => {
  emit("selectChange", selection);
};
// 当某一行被点击时会触发该事件
const selectAll = (val) => {
  emit("select-all", val);
};
const getIndex = computed(() => {
  return ((props.queryParams.pageNum - 1) * props.queryParams.pageSize) || 0;
});
// 暴露方法给父组件调用
defineExpose({ clearSelection, toggleRowSelections, setCurrent,tableRef });

style部分

<style lang="scss" scoped>
.left {
  text-align: right;
  position: relative;
  padding-left: 10px;
}

.left::after {
  content: "";
  width: 100%;
  height: 0px;
  position: absolute;
  border-bottom: 1px solid #ccc;
  top: 0;
  left: 0;
  transform: rotate(-12deg);
}

.right {
  text-align: left;
  padding-right: 10px;
}

:deep(.el-table__cell) {
  border: 1px solid #ebeef5 !important;
}

/* 选中行样式 */
::v-deep(.el-table__body tr.current-row > td) {
  background-color: #fffff5 !important;
  border-top: 1px solid #facd91 !important;
  border-bottom: 1px solid #facd91 !important;
}
</style>