npm package: @pluve/lego-table-vue
Description: 乐高系列之 table 组件
Author: yangwend
Latest version: 0.7.2

# @pluve/lego-table-vue

乐高系列之 `table` 组件系列

[![npm (scoped)](https://img.shields.io/npm/v/@pluve/lego-table-vue?style=for-the-badge)](https://www.npmjs.com/package/@pluve/lego-table-vue)

`@pluve/lego-table-vue` 已经投入了我们的生产环境中使用，经受住了来自真实业务的考验，并伴随着我们的业务需求不断完善。

## 安装

```bash
# 依赖 vue@3.x/ant-design-vue@3.x
yarn add @pluve/lego-table-vue
```

## LegoTable

基于 `ant-design-vue` `table` 组件进行二次封装的 `table` 组件，建议配合 [`@pluve/use-antd-table-vue`](https://www.npmjs.com/package/@pluve/use-antd-table-vue) 使用。**样式部分**建议配合 `YF antd` 公用样式文件 `antd-rest-1.0.0.css` 使用。

### 特性
* 基于 `ant-design-vue` `table` 组件进行二次封装
* 与 `ant-design-vue` `table` 组件 `API` **完全对齐**
* 提供**部分属性默认配置**，使用者可以针对属性自定义配置
  
### 默认配置
| 属性 | 默认值 | 描述 |
| --- | --- | --- |
| pagination | 参见 <a href="#pagination">pagination</a> | 分页器 |
| onChange | `pageSize` 变化或点击排序时会**重置 `current` 为 `1`** | 选中项发生变化时的回调 |

### pagination
| 属性 | 默认值 | 描述 |
| --- | --- | --- |
| pageSizeOptions | `['10', '15', '20', '50', '100']` | 指定每页可以显示多少条 |
| showQuickJumper | true | 是否可以快速跳转至某页 |
| showSizeChanger | true | 是否可以改变 `pageSize` |
| showTotal | 共有total 条记录，每页显示pageSize条 | 用于显示数据总量和当前数据顺序 |

## LegoTableColEllipsis

一般用于 `table` 列超长展示缩略场景。

为了适应在不同屏幕宽度下缩略宽度自适应，组件对其做了一些处理，**最大宽度计算公式**为：`${((props.maxWidth ?? 576) * 100) / (props.screenWidthBase ?? 1920)}vw`。

使用时，按照 `1920` 屏幕宽度展示时该列最大能展示多少 `maxWidth` 直接赋值即可。

**建议**：在需要进行缩略处理的 `column` 这一列，设置一个宽度(保证该列表表头不会换行即可)，此时在屏幕宽度变化时，缩略的这一列始终能够撑满。见下面例子

### API

| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| title | `table` 列需要展示的文案 | `string \| slot` | `''` |
| maxWidth | 超`maxWidth`宽度则缩略展示 | `number` | 576 |
| showTooltip | 是否缩略展示时以 `tooltip` 形式展示 | `boolean` | true |
| screenWidthBase | 屏幕宽度基准 | `number` | 1920 |

## 效果展示

![demo 截图](https://yf-test-oss.yifengx.com/webtest/pluve/static/lego-table-demo.gif)

### 使用示例

```vue
<template>
  <div :class="$style.wrap">
    <LegoTable bordered :columns="columns" :data-source="state.list" :pagination="state.pagination" :scroll="{ x: 'max-content' }" @change="onChange">
      <template #bodyCell="{ text, column }">
        <template v-if="column.dataIndex === 'work'">
          <LegoTableColEllipsis :max-width="900">
            <template #title>
              <div>{{ text }}</div>
            </template>
          </LegoTableColEllipsis>
        </template>
      </template>
    </LegoTable>
  </div>
</template>
<script setup lang="ts">
import { LegoTable, LegoTableColEllipsis } from '@pluve/lego-table-vue';
import { reactive, onMounted } from 'vue';
import type { ColumnsType } from 'ant-design-vue/es/table';
import type { TablePaginationConfig } from 'ant-design-vue/es/table';

const columns: ColumnsType<any> = [
  {
    title: '姓名',
    dataIndex: 'name',
  },
  {
    title: '手机号',
    dataIndex: 'phone',
  },
  {
    title: '年龄',
    dataIndex: 'age',
  },
  {
    title: '工作',
    dataIndex: 'work',
    width: 60, // 设置该列的宽度，小于该字段缩略时设置的mxWidth即可，建议设置值保证表头该列不换行即可
  },
];

const state = reactive<{
  list: {
    name: string;
    age: number;
    work: string;
    phone: string;
  }[];
  pagination: {
    current: number;
    pageSize: number;
    total: number;
  };
}>({
  list: [],
  pagination: {
    current: 1,
    pageSize: 10,
    total: 100,
  },
});

onMounted(() => {
  state.list = [...new Array(10)].map((item, index) => ({
    name: `杨坤${index}`,
    age: 30 + Math.ceil(index * Math.random()),
    work: `我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串${index}`,
    phone: `188****345${index}`,
  }));
});

const onChange = (pagination: TablePaginationConfig) => {
  state.pagination.current = pagination.current!;
  state.pagination.pageSize = pagination.pageSize!;

  state.list = [...new Array(pagination.pageSize)].map((item, index) => ({
    name: `杨坤${index}`,
    age: 50 + Math.ceil(index * Math.random()),
    work: `我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串我是一个很长的字符串${index}`,
    phone: `184****345${index}`,
  }));
};
</script>

<style lang="less" module>
.wrap {
  position: relative;
  min-height: 52px;
  background-color: #fff;
  padding: 10px 10px 0;
  border-radius: 4px;
  margin-top: 10px;
}
</style>
```

## TODO

- 支持虚拟化