Skip to content

About VTable

Common Issues

1. The table state is abnormal, such as the expansion or selection is abnormal?

Please check if the rowKey property is configured, if configured, please ensure that the value of rowKey is unique, otherwise the table state may be abnormal.

2. The position of a row is not accurate or the table scrolls abnormally?

Please check if the rowHeight property is set, if set, please ensure that the value of rowHeight is correct, otherwise the position of a row may not be accurate.

3. It is recommended to use the bodyCell slot instead of the customCell function in the column

The reason is that bodyCell internally does caching processing, which can avoid unnecessary cell redrawing, while the customCell function will be called repeatedly.

4. The problem of multiple triggers of scroll loading

You need to pass in the loading state, which is used to control the problem of frequent triggers.

5. The pagination component cannot be displayed?

The display of the pagination component depends on two values paginationConfig.enabled and paginationConfig.total, both must be set to display.

6. When setting the pagination state, both properties must be passed in

vue
// Incorrect passing ❌
<VTable :default-pagination="{ pageSize: 5 }"></VTable>

// Correct passing ✅
<VTable :default-pagination="{ pageSize: 5, pageIndex: 1 }"></VTable>

6. How to customize the secondary encapsulation of the built-in components such as checkbox pagination?

The following code is a secondary encapsulation inside the company (simplified processing, but the basic logic is enough)

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>

Last updated: