Skip to content

关于 VTable

常见问题

1. 表格状态异常,例如展开或者选择异常?

请检查是否配置了 rowKey 属性,如果配置了,请确保 rowKey 的值是唯一的,否则可能会出现表格状态异常的情况。

2. 滚动到某一行位置不精确或者表格滚动异常?

请检查是否设置了 rowHeight 属性,如果设置了,请确保 rowHeight 的值是正确的,否则可能会出现滚动到某一行位置不精确的情况。

3. 优先推荐使用 bodyCell 插槽,而不是 columncustomCell 函数

原因是 bodyCell 内部做了缓存处理,可以避免不必要的单元格重绘,而 customCell 函数则会每次都重新调用。

4. 滚动加载多次触发的问题

你需要传入 loading 状态,用于控制频繁触发的问题

5. 表格无法显示分页器?

分页器的显示与否,取决于两个值 paginationConfig.enabledpaginationConfig.total,二者同时设置才会显示

6. 设置分页状态时,务必两个属性均要传入

vue
// 错误传递 ❌
<VTable :default-pagination="{ pageSize: 5 }"></VTable>

// 正确传递 ✅
<VTable :default-pagination="{ pageSize: 5, pageIndex: 1 }"></VTable>

6. 如何自定义 checkbox pagination 等内置组件做二次封装?

下面代码是笔者公司内部的二次封装(做了简化处理,不过大致逻辑已经够了)

vue
<template>
  <VirtualTable :ref="componentRef" class="custom-table" v-bind="computedProps">
    <template v-for="(_, name) in slots" #[name]="slotProps">
      <slot :name="name" v-bind="slotProps" />
    </template>

    <template #customPopover="{ open, onOpenChange, trigger, content }">
      <component
        :is="
          h(
            Popover,
            {
              open,
              onOpenChange,
              placement: 'bottomLeft',
              trigger: 'click',
              overlayInnerStyle: { padding: 0 },
              arrow: false,
            },
            { default: trigger, content },
          )
        "
      />
    </template>
    <template #customCheckbox="{ checked, indeterminate, disabled, onCheckedChange }">
      <a-checkbox
        :checked="checked"
        :disabled="disabled"
        :indeterminate="indeterminate"
        @change="onCheckedChange($event as any)"
        @click.stop
      />
    </template>
    <template #customPagination="{ pageIndex, pageSize, total, onPageChange }">
      <a-pagination
        class="pr-24"
        :current="pageIndex"
        :page-size="pageSize"
        :total="total"
        v-bind="props.paginationConfig.paginationExtraProps"
        @change="onPageChange"
      />
    </template>
    <template #customEmpty>
      <a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" />
    </template>
    <template #customSorterIcon="{ sort }">
      <SorterIcon :sort="sort" />
    </template>
  </VirtualTable>
</template>

<script setup lang="ts" generic="TData extends VTableData">
import { h } from 'vue'
import { commonThemeRGB } from '@/const/theme'
import { deepAssign } from '@/utils/object'
import VirtualTable, {
  vTableDefaultProps,
  type VTableData,
  type VTableInstance,
  type VTableProps,
  type VTableSlots,
} from '@aimerthyr/virtual-table'
import { Empty, Popover } from 'ant-design-vue'

defineOptions({
  name: 'VTable',
})

// #region 属性定义
// eslint-disable-next-line vue/no-unused-properties, vue/prop-name-casing
const props = withDefaults(defineProps<VTableProps<TData>>(), {
  ...vTableDefaultProps,
})
const computedProps = computed<VTableProps<TData>>(() => {
  return {
    ...props,
    themeConfig: deepAssign(
      {
        primaryColor: `rgb(${commonThemeRGB.colorPrimaryRGB})`,
        header: {
          backgroundColor: '#fff',
        },
      },
      props.themeConfig as any,
    ),
  }
})
// #endregion

// #region 插槽定义
const slots = defineSlots<VTableSlots<TData>>()
// #endregion

// #region 实例定义
const vm = getCurrentInstance()
const componentRef = (instance: any) => {
  vm!.exposeProxy = vm!.exposed = instance || {}
}
defineExpose({} as VTableInstance)
// #endregion
</script>

<style lang="less" scoped>
.custom-table {
  :deep(.v-table-header tr) {
    th.checkbox-col {
      padding-right: 0;
      text-align: right !important;
    }
    th:last-child {
      padding-right: 24px;
    }
  }
  :deep(.v-table-body tr) {
    td.checkbox-col {
      padding-right: 0;
      text-align: right !important;
    }
    td:last-child {
      padding-right: 24px;
    }
  }
}
</style>

最后更新时间: