Skip to content

关于 VTable

常见问题

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

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

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

请检查是否设置了 rowHeight 属性,如果设置了,请确保 rowHeight 的值是正确的,否则可能会出现滚动到某一行位置不精确的情况。重要:如果你的行高不固定(例如,文字可以换行之类的),则不要设置行高

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

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

4. 如何设置表格内容宽度自适应

你可以通过设置 maxTableWidth 属性为 max-content ,此时每一列的内容会自适应自己的列宽,不会换行。(其余情况下,表格会对每一列进行换行显示)。

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

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

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

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

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

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

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

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

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

vue
<template>
  <VirtualTable :ref="componentRef" class="custom-table" v-bind="computedProps">
    <template v-for="(_, name) in computedSlots" #[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>>()
const computedSlots = computed<VTableSlots<TData>>(() => {
  const {
    /* eslint-disable */
    customFilterDropdown,
    customFilterIcon,
    customPopover,
    customCheckbox,
    customPagination,
    customEmpty,
    customSorterIcon,
    /* eslint-enable */
    ...rest
  } = slots
  return rest
})
// #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>

最后更新时间: