封装table表格

71 阅读1分钟

接触新项目的时候,经常会看到之前的同事二次封装了table表格,代码贴出来

<template>
  <el-table :data="data" border v-loading="loading">
    <el-table-column v-for="col in filterColumns" :key="col.label" v-bind="col">
      <template v-if="col.slot" #="{ row }">
        <slot :name="col.slot" :row="row"></slot>
      </template>
    // 实现自定义需求
      <template v-else #="{ row }">
        {{ row[col.prop] || "-" }}
      </template>
      <template v-if="col.label === '操作'" #header>
        <el-popover
          placement="bottom"
          :width="80"
          trigger="click"
          :visible="visible"
        >
          <template #reference>
            <div class="title" @click="visible = true">
              <span>操作</span>
              <el-icon><ArrowDown /></el-icon>
            </div>
          </template>
          <el-checkbox-group v-model="tempCheckedLabels">
            <el-checkbox
              :label="item.label"
              v-for="item in cbColumns"
              :key="item.label"
            />
          </el-checkbox-group>

          <div>
            <el-button size="small" @click="cancel">取消</el-button>
            <el-button size="small" type="primary" @click="confirm"
              >确定</el-button
            >
          </div>
        </el-popover>
      </template>
    </el-table-column>
  </el-table>

  <el-pagination
    class="mt-20"
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    :total="total"
    :page-sizes="[10, 20, 30, 40]"
    layout="prev, pager, next, jumper, ->, sizes, total"
    @current-change="getList"
    @size-change="getList"
  >
  </el-pagination>
</template>

<script lang="ts">
export default {
  name: "XTable",
};
</script>

<script lang="ts" setup>
import { onMounted, ref, computed } from "vue";
import { ArrowDown } from "@element-plus/icons-vue";

const props = withDefaults(
  defineProps<{
    columns: any[];
    getData: (page: number, limit: number) => {};
    pagination: boolean;
  }>(),
  {
    pagination: true,
  }
);

const data = ref<any[]>([]);
const loading = ref(false);
const currentPage = ref(1);
const pageSize = ref(10);
const total = ref(0);

const getList = async () => {
  loading.value = true;
  const result: any = await props.getData(currentPage.value, pageSize.value);
  data.value = result.records;
  total.value = result.total;
  loading.value = false;
};

onMounted(() => {
  getList();
});

const visible = ref(false);
const checkedLabels = ref(props.columns.map((col) => col.label)); // 确定时才改变
const tempCheckedLabels = ref(checkedLabels.value); // 选择时会自动改变  取消时恢复为checkedLabels
const filterColumns = computed(() => {
  // 要显示的列
  return props.columns.filter((col) => checkedLabels.value.includes(col.label));
});
const cbColumns = computed(() => {
  // 要显示的所有checkbox对应的列
  return props.columns.filter((col) => col.label !== "操作");
});
// 取消
const cancel = () => {
  visible.value = false;
  tempCheckedLabels.value = checkedLabels.value;
};
// 确定
const confirm = () => {
  visible.value = false;
  checkedLabels.value = tempCheckedLabels.value;
};
</script>

<style scoped>
.title {
  width: 80px;
  display: flex;
  align-items: center;
}
</style>