当前位置:   article > 正文

vue3 ts element-plus vite--表格封装_vue3表格封装

vue3表格封装

主要做学习记录--原文

https://blog.csdn.net/weixin_45291937/article/details/125523244

学习成果--简单element-plus--表格封装:

1.因为element会废弃Pagination 事件---v-model和"事件"均有案例

效果图:

1.创建Table.vue

   src/components/Table/index.vue

  1. <template>
  2. <div class="home">
  3. <el-table
  4. :border="true"
  5. style="width: 100%"
  6. height="100%"
  7. :data="tableData"
  8. :header-cell-style="{ backgroundColor: '#f5f5f5' }"
  9. :cell-style="{ padding: '5px' }"
  10. >
  11. <template #empty>
  12. <el-empty description="暂无数据"></el-empty>
  13. </template>
  14. <template v-for="column in columns" :key="column.prop || column.key">
  15. <el-table-column
  16. label="序号"
  17. width="100"
  18. :align="column.align"
  19. v-if="column.label == '序号'"
  20. >
  21. <template #default="scope">
  22. <slot name="xiuhao" :scope="scope">
  23. <span
  24. >{{
  25. scope.$index +
  26. (pagination.currentPage - 1) * pagination.pageSize +
  27. 1
  28. }}
  29. </span>
  30. </slot>
  31. </template>
  32. </el-table-column>
  33. <el-table-column
  34. v-else-if="column.slot"
  35. :label="column.label"
  36. :width="column.width"
  37. header-:align="column.align"
  38. :align="column.align"
  39. >
  40. <template #default="scope">
  41. <slot :name="column.slot" :scope="scope"></slot>
  42. </template>
  43. </el-table-column>
  44. <el-table-column
  45. v-else
  46. :label="column.label"
  47. :width="column.width"
  48. :prop="column.prop"
  49. show-overflow-tooltip
  50. :align="column.align"
  51. >
  52. <template #default="{ row, $index }">
  53. <!-- 对时间处理 -->
  54. <template v-if="column.type === 'date'">
  55. <span>{{
  56. timeFormat(
  57. row[column.prop as string],
  58. column.dateFormat as string
  59. )
  60. }}</span>
  61. </template>
  62. </template></el-table-column
  63. >
  64. </template>
  65. </el-table>
  66. <!-- <div class="pagination">
  67. <el-pagination
  68. style="margin-top: 12px"
  69. :current-page="pagination.currentPage"
  70. :page-sizes="pagination.pageSizes"
  71. :page-size="pagination.pageSize"
  72. layout="total, sizes, prev, pager, next, jumper"
  73. :total="pagination.total"
  74. @size-change="pageSizeChange"
  75. @current-change="currentPageChange"
  76. prev-text="上一页"
  77. next-text="下一页"
  78. hide-on-single-page
  79. >
  80. </el-pagination>
  81. </div> -->
  82. <div class="pagination">
  83. <el-pagination
  84. style="margin-top: 12px"
  85. v-model:current-page="pagination.currentPage"
  86. v-model:page-sizes="pagination.pageSizes"
  87. v-model:page-size="pagination.pageSize"
  88. layout="total, sizes, prev, pager, next, jumper"
  89. v-model:total="pagination.total"
  90. hide-on-single-page
  91. >
  92. </el-pagination>
  93. </div>
  94. </div>
  95. </template>
  96. <script lang="ts" setup>
  97. import { toRefs, reactive, watch } from "vue";
  98. import { timeFormat } from "@/utils/common";
  99. interface TableProps {
  100. tableData: Array<object>; // table的数据
  101. columns: Table.Column[]; // 每列的配置项
  102. pagination: Table.Pagination; //页码
  103. }
  104. const props = defineProps<TableProps>();
  105. interface EmitEvent {
  106. (e: "selection-change", params: any): void; // 当选择项发生变化时会触发该事件
  107. (e: "size-change", pageSize: number): void; // pageSize事件
  108. (e: "current-change", currentPage: number): void; // currentPage按钮组事件
  109. (e: "pagination-change", pagination: object): void; //pageSize事件和currentPage按钮组事件
  110. }
  111. // 使用 v-model 放弃elemntui-Pagination方法
  112. // 监听 current-page , page-size 的改变,
  113. const emit = defineEmits<EmitEvent>();
  114. const { pagination } = toRefs(props);
  115. watch(
  116. () => pagination.value.currentPage,
  117. (newValue, oldValue) => {
  118. pagination.value.currentPage = newValue;
  119. emit("pagination-change", pagination);
  120. }
  121. );
  122. watch(
  123. () => pagination.value.pageSize,
  124. (newValue, oldValue) => {
  125. pagination.value.pageSize = newValue;
  126. pagination.value.currentPage = 1;
  127. emit("pagination-change", pagination);
  128. }
  129. );
  130. /*
  131. * 注册分页 change 方法
  132. */
  133. // const emit = defineEmits<EmitEvent>();
  134. // const { pagination } = toRefs(props);
  135. // // 切换pageSize
  136. // const pageSizeChange = (pageSize: number) => {
  137. // pagination.value.pageSize = pageSize;
  138. // pagination.value.currentPage = 1;
  139. // emit("pagination-change", pagination);
  140. // };
  141. // // 切换currentPage
  142. // const currentPageChange = (currentPage: number) => {
  143. // pagination.value.currentPage = currentPage;
  144. // emit("pagination-change", pagination);
  145. // };
  146. </script>
  147. <style lang="scss" scoped>
  148. .home {
  149. width: 100%;
  150. height: 100%;
  151. }
  152. .pagination {
  153. width: 100%;
  154. display: flex;
  155. margin-top: 10px;
  156. justify-content: flex-end;
  157. }
  158. .el-tooltip__popper {
  159. max-width: 20% !important;
  160. }
  161. .el-tooltip__popper,
  162. .el-tooltip__popper.is-dark {
  163. background: rgb(48, 65, 86) !important;
  164. color: #fff !important;
  165. line-height: 20px;
  166. }
  167. </style>

2.创建 index.d.ts 声明为全局的类型

   src/components/Table/index.d.ts

  1. // table表格
  2. declare namespace Table {
  3. type VNodeChild = import("vue").VNodeChild;
  4. type Type = "selection" | "index" | "expand" | "image" | "date";
  5. type Size = "large" | "default" | "small";
  6. type Align = "center" | "left" | "right";
  7. type Command = string | number;
  8. type DateFormat =
  9. | "yyyy-MM-dd"
  10. | "yyyy-MM-dd hh:mm:ss"
  11. | "yyyy-MM-DD hh:mm"
  12. | "yyyy-MM";
  13. type Order = "ascending" | "descending";
  14. interface ButtonItem {
  15. name: string;
  16. command: Command;
  17. size?: Size;
  18. type?: "primary" | "success" | "warning" | "danger" | "info";
  19. }
  20. interface
  21. interface Sort {
  22. prop: string;
  23. order: Order;
  24. init?: any;
  25. silent?: any;
  26. }
  27. interface Column {
  28. // 对应列的类型。 如果设置了selection则显示多选框; 如果设置了 index 则显示该行的索引(从 1 开始计算); 如果设置了 expand 则显示为一个可展开的按钮
  29. type?: Type;
  30. label?: string;
  31. prop?: string;
  32. slot?: string;
  33. width?: string;
  34. align?: Align;
  35. dateFormat?: DateFormat; // 显示在页面中的日期格式,简单列举了几种格式, 可自行配置
  36. showOverflowTooltip?: boolean;
  37. buttons?: ButtonItem[];
  38. render?: (row?: Record<string, any>, index?: number) => VNodeChild; // 渲染函数,渲染这一列的每一行的单元格
  39. sortable?: boolean | "custom"; // 对应列是否可以排序, 如果设置为 'custom',则代表用户希望远程排序,需要监听 Table 的 sort-change 事件
  40. headerRender?: ({ column, index }) => VNodeChild; // 渲染函数,渲染列表头
  41. headerSlot?: string; // 自定义表头插槽名字
  42. children?: Column[]; // 配置多级表头的数据集合, 具体用法可参考多级表头使用示例。
  43. }
  44. interface Options {
  45. height?: string | number;
  46. // Table 的高度, 默认为自动高度。 如果 height 为 number 类型,单位 px;如果 height 为 string 类型,则这个高度会设置为 Table 的 style.height 的值,Table 的高度会受控于外部样式。
  47. stripe?: boolean; // 是否为斑马纹 table
  48. maxHeight?: string | number; // Table 的最大高度。 合法的值为数字或者单位为 px 的高度。
  49. size?: Size; // Table 的尺寸
  50. showHeader?: boolean; // 是否显示表头,
  51. tooltipEffect?: "dark" | "light"; // tooltip effect 属性
  52. showPagination?: boolean; // 是否展示分页器
  53. paginationConfig?: Pagination; // 分页器配置项,详情见下方 paginationConfig 属性,
  54. rowStyle?: ({ row, rowIndex }) => stirng | object; // 行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style。
  55. headerCellStyle?: import("vue").CSSProperties; // 表头单元格的style样式,是一个object为所有表头单元格设置一样的 Style。注:CSSProperties类型就是一个对象,像正常在style中写css一样 {color: #f00}
  56. defaultSort?: Sort; // 默认的排序列的 prop 和顺序。 它的 prop 属性指定默认的排序的列,order 指定默认排序的顺序。
  57. rowKey?: string; // 行数据的 Key,用来优化 Table 的渲染。
  58. }
  59. interface Pagination {
  60. total?: number; // 总条目数
  61. currentPage: number; // 当前页数,支持 v-model 双向绑定
  62. pageSize: number; // 每页显示条目个数,支持 v-model 双向绑定
  63. pageSizes?: number[]; // 每页显示个数选择器的选项设置
  64. layout?: string; // 组件布局,子组件名用逗号分隔
  65. background?: boolean; // 是否为分页按钮添加背景色
  66. }
  67. }

3.创建 common.ts

   src/utils/common.ts

  1. **
  2. * 时间戳转时间
  3. * @param {Number} date 时间戳
  4. * @param {String} format 需要的格式
  5. * @return {String} 返回格式化完成时间
  6. */
  7. interface timeFormat {
  8. (date: Date | any, format: string): String;
  9. }
  10. export const timeFormat: timeFormat = (date, format) => {
  11. date = new Date(date);
  12. if (date == "Invalid Date") {
  13. return "";
  14. }
  15. let map: any = {
  16. M: date.getMonth() + 1, //月份
  17. d: date.getDate(), //日
  18. h: date.getHours(), //小时
  19. m: date.getMinutes(), //分
  20. s: date.getSeconds(), //秒
  21. q: Math.floor((date.getMonth() + 3) / 3), //季度
  22. S: date.getMilliseconds(), //毫秒
  23. };
  24. format = format.replace(/([yMdhmsqS])+/g, function (all: any, t: any) {
  25. var v = map[t];
  26. if (v !== undefined) {
  27. if (all.length > 1) {
  28. v = "0" + v;
  29. v = v.substr(v.length - 2);
  30. }
  31. return v;
  32. } else if (t === "y") {
  33. return (date.getFullYear() + "").substr(4 - all.length);
  34. }
  35. return all;
  36. });
  37. return format;
  38. };

4.引用

  1. <template>
  2. <div>
  3. <!-- <div style="height: 400px">
  4. <Table
  5. :columns="tableColumn"
  6. :table-data="tableData"
  7. :pagination="pagination"
  8. @pagination-change="paginationChange"
  9. >
  10. <template v-slot:xb="{ scope }">
  11. <span> {{ scope.row.gender }}</span>
  12. </template>
  13. </Table>
  14. </div> -->
  15. <div style="height: 400px">
  16. <Table
  17. :columns="tableColumn"
  18. :table-data="tableData"
  19. v-model:pagination="pagination"
  20. @pagination-change="paginationChange"
  21. >
  22. <template v-slot:xb="{ scope }">
  23. <span> {{ scope.row.gender }}</span>
  24. </template>
  25. </Table>
  26. </div>
  27. </div>
  28. </template>
  29. <script setup lang="ts">
  30. import Table from "@/components/Table/index.vue";
  31. import { reactive } from "vue";
  32. interface User {
  33. date: number;
  34. name: string;
  35. address: string;
  36. gender: number;
  37. }
  38. const tableData = reactive<User[]>([
  39. {
  40. date: 1660737564000,
  41. name: "佘太君",
  42. address: "上海市普陀区金沙江路 1516 弄",
  43. gender: 0,
  44. },
  45. {
  46. date: 1462291200000,
  47. name: "王小虎",
  48. address: "上海市普陀区金沙江路 1517 弄",
  49. gender: 0,
  50. },
  51. {
  52. date: 1462032000000,
  53. name: "王小帅",
  54. address: "上海市普陀区金沙江路 1519 弄",
  55. gender: 1,
  56. },
  57. {
  58. date: 1462204800000,
  59. name: "王小呆",
  60. address: "上海市普陀区金沙江路 1516 弄",
  61. gender: 1,
  62. },
  63. {
  64. date: 1462204800000,
  65. name: "王小呆",
  66. address: "上海市普陀区金沙江路 1516 弄",
  67. gender: 1,
  68. },
  69. {
  70. date: 1462204800000,
  71. name: "王小呆",
  72. address: "上海市普陀区金沙江路 1516 弄",
  73. gender: 1,
  74. },
  75. {
  76. date: 1462204800000,
  77. name: "王小呆",
  78. address: "上海市普陀区金沙江路 1516 弄",
  79. gender: 1,
  80. },
  81. {
  82. date: 1462204800000,
  83. name: "王小呆",
  84. address: "上海市普陀区金沙江路 1516 弄",
  85. gender: 1,
  86. },
  87. {
  88. date: 1462204800000,
  89. name: "王小呆",
  90. address: "上海市普陀区金沙江路 1516 弄",
  91. gender: 1,
  92. },
  93. {
  94. date: 1462204800000,
  95. name: "王小呆",
  96. address: "上海市普陀区金沙江路 1516 弄",
  97. gender: 1,
  98. },
  99. ]);
  100. const tableColumn = reactive<Table.Column[]>([
  101. { label: "序号" },
  102. { prop: "name", width: "100", label: "名字", align: "center" },
  103. { prop: "gender", width: "100", label: "性别", slot: "xb", align: "center" },
  104. {
  105. prop: "address",
  106. label: "地址",
  107. headerSlot: "addressHeader",
  108. showOverflowTooltip: true,
  109. align: "center",
  110. },
  111. {
  112. type: "date",
  113. prop: "date",
  114. label: "时间",
  115. align: "center",
  116. width: "150",
  117. dateFormat: "yyyy-MM-dd",
  118. },
  119. ]);
  120. const pagination = reactive<Table.Pagination>({
  121. total: 20,
  122. currentPage: 1,
  123. pageSize: 10,
  124. pageSizes: [5, 10, 15, 20],
  125. });
  126. // table 传递的数据
  127. const paginationChange = (res: any) => {
  128. console.log(res.value,pagination.currentPage);
  129. };
  130. </script>
  131. <style scoped></style>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/684237
推荐阅读
相关标签
  

闽ICP备14008679号