翼度科技»论坛 编程开发 JavaScript 查看内容

vue3基于elementplus 简单实现表格二次封装过程

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
公司渲染表格数据时需要将空数据显示‘-’,并且对于每一列数据的显示也有一定的要求,基于这个需求对element-plus简单进行了二次封装。
具体包括以下几点(持续更新中):
1.空数据显示‘-’
2.固定表格高度
3.支持多选表格
4. 自定义列宽
  1. <template>
  2.   <div>
  3.     <el-table
  4.       :data="dataSource"
  5.       v-loading="loading"
  6.       :height="vdaH"
  7.       :max-height="vdaH"
  8.       :fit="fit"
  9.       :border="border"
  10.       :header-cell-class-name="headerCellClassName"
  11.       highlight-current-row
  12.       :tooltip-options="{
  13.         effect: 'dark',
  14.         placement: 'bottom',
  15.         showArrow: true,
  16.       }"
  17.       show-overflow-tooltip
  18.       @selection-change="handleSelectionChange"
  19.     >
  20.       <el-table-column
  21.         v-if="isMoreSelect"
  22.         type="selection"
  23.         width="55"
  24.         :selectable="handleSelectable"
  25.       />
  26.       <el-table-column type="index" label="序号" width="55" />
  27.       <template v-for="(column, index) in columns" :key="index">
  28.         <el-table-column
  29.           show-overflow-tooltip
  30.           v-if="column.scopeVal"
  31.           :prop="column.prop"
  32.           :label="column.label"
  33.           :min-width="column.width || column.label.length * 20 + 20"
  34.         >
  35.           <template #default="scope">
  36.             <slot
  37.               :column="column"
  38.               :record="scope.row"
  39.               :text="scope.row[column.prop]"
  40.               :index="dataSource.indexOf(scope.row)"
  41.               :name="column.prop"
  42.             >
  43.             </slot>
  44.           </template>
  45.         </el-table-column>
  46.         <!-- :min-width="column.width || column.label.length * 20 + 20" -->
  47.         <el-table-column
  48.           v-else
  49.           :prop="column.prop"
  50.           :label="column.label"
  51.           :min-width="
  52.             column.width ||
  53.             getColumnWidth(column.label, column.prop, dataSource)
  54.           "
  55.         >
  56.           <template #default="{ row }">
  57.             {{ checkEmpty(row[column.prop]) }}
  58.           </template>
  59.         </el-table-column>
  60.       </template>
  61.       <!-- 操作 -->
  62.       <el-table-column
  63.         v-if="!hideOperation"
  64.         fixed="right"
  65.         label="操作"
  66.         align="center"
  67.         :width="operationWidth"
  68.       >
  69.         <template #default="scope">
  70.           <slot v-bind="scope"></slot>
  71.         </template>
  72.       </el-table-column>
  73.     </el-table>
  74.     <div class="pagination">
  75.       <el-pagination
  76.         v-show="totalNum > 0"
  77.         @size-change="handleSizeChange"
  78.         @current-change="handleCurrentChange"
  79.         v-model:current-page.sync="page"
  80.         :page-sizes="[10, 20, 50, 100]"
  81.         v-model:page-size="size"
  82.         layout="total, sizes, prev, pager, next, jumper"
  83.         :total="totalNum"
  84.         background
  85.         small
  86.       />
  87.     </div>
  88.   </div>
  89. </template>
  90. <script lang="ts" setup>
  91. import { checkEmpty, getColumnWidth } from "@/utils/util";
  92. const props = defineProps({
  93.   dataSource: {
  94.     type: Array<any>,
  95.     default: () => [],
  96.   },
  97.   columns: {
  98.     type: Array<any>,
  99.     default: () => [],
  100.   },
  101.   vdaH: {
  102.     type: Number,
  103.     default: 300,
  104.   },
  105.   hideOperation: {
  106.     type: Boolean,
  107.     default: false,
  108.   },
  109.   operationWidth: {
  110.     type: String,
  111.     default: "100",
  112.   },
  113.   loading: {
  114.     type: Boolean,
  115.     default: false,
  116.   },
  117.   //是否多选显示
  118.   isMoreSelect: {
  119.     type: Boolean,
  120.     default: false,
  121.   },
  122.   fit: {
  123.     type: Boolean,
  124.     default: true,
  125.   },
  126.   border: {
  127.     type: Boolean,
  128.     default: false,
  129.   },
  130.   headerCellClassName: {
  131.     type: String,
  132.     default: "custmorTableHeader",
  133.   },
  134.   // 当前页
  135.   currentPage: {
  136.     type: Number,
  137.     default: 0,
  138.   },
  139.   // 展示页数
  140.   pageSize: {
  141.     type: Number,
  142.     default: 0,
  143.   },
  144.   //总页数
  145.   totalNum: {
  146.     type: Number,
  147.     default: 0,
  148.   },
  149.   //多选
  150.   handleSelection: {
  151.     type: Function,
  152.     default: () => {},
  153.   },
  154. });
  155. // // 测试列宽
  156. // /**
  157. //  * el-table扩展工具  -- 列宽度自适应
  158. //  * @param {*} prop 字段名称(string)
  159. //  * @param {*} records table数据列表集(array)
  160. //  * @returns 列宽(int)
  161. //  */
  162. // function getColumnWidth(prop: string, records: any) {
  163. //   const minWidth = 80; // 最小宽度
  164. //   const padding = 12; // 列内边距
  165. //   const contentWidths = records.map((item: any) => {
  166. //     console.log("item", item);
  167. //     console.log("PROP", prop);
  168. //     const value = item[prop] ? String(item[prop]) : "";
  169. //     const textWidth = getTextWidth(value);
  170. //     return textWidth + padding;
  171. //   });
  172. //   console.log("contentWidths", contentWidths);
  173. //   let maxWidth = Math.max(...contentWidths);
  174. //   if (maxWidth > 240) {
  175. //     maxWidth = 240;
  176. //   }
  177. //   return Math.max(minWidth, maxWidth);
  178. // }
  179. // /**
  180. //  * el-table扩展工具  -- 列宽度自适应 - 获取列宽内文本宽度
  181. //  * @param {*} text 文本内容
  182. //  * @returns 文本宽度(int)
  183. //  */
  184. // function getTextWidth(text: string) {
  185. //   const span = document.createElement("span");
  186. //   span.style.visibility = "hidden";
  187. //   span.style.position = "absolute";
  188. //   span.style.top = "-9999px";
  189. //   span.style.whiteSpace = "nowrap";
  190. //   span.innerText = text;
  191. //   document.body.appendChild(span);
  192. //   const width = span.offsetWidth + 5;
  193. //   document.body.removeChild(span);
  194. //   return width;
  195. // }
  196. // ...其他方法
  197. const emit = defineEmits([
  198.   "pagination",
  199.   "update:currentPage",
  200.   "update:pageSize",
  201.   "selection-change",
  202. ]);
  203. const page = useVModel(props, "currentPage", emit);
  204. const size = useVModel(props, "pageSize", emit);
  205. function handleSizeChange(val: number) {
  206.   emit("pagination", { currentPage: page, pageSize: val });
  207. }
  208. function handleCurrentChange(val: number) {
  209.   // console.log("val", val);
  210.   page.value = val;
  211.   emit("pagination", { currentPage: val, pageSize: props.pageSize });
  212. }
  213. const handleSelectionChange = (val: any) => {
  214.   emit("selection-change", val);
  215. };
  216. const handleSelectable = (row: any) => {
  217.   // console.log("row", row);
  218.   return row.selectable;
  219. };
  220. </script>
  221. <style lang="scss" scoped>
  222. .pagination {
  223.   display: flex;
  224.   justify-content: end;
  225.   padding: 12px;
  226.   margin-top: 5px;
  227.   &.hidden {
  228.     display: none;
  229.   }
  230. }
  231. </style>
复制代码
对于表格列宽实现了根据数据长度进行每一列的展示:
  1. /**
  2. * el-table扩展工具  -- 列宽度自适应
  3. * @param {*} prop 字段名称(string)
  4. * @param {*} records table数据列表集(array)
  5. * @returns 列宽(int)
  6. */
  7. export function getColumnWidth(label: string, prop: string, tableData: any) {
  8.   //label表头名称
  9.   //prop对应的内容
  10.   //tableData表格数据
  11.   const minWidth = 90; // 最小宽度
  12.   const padding = 10; // 列内边距
  13.   const arr = tableData.map((item: any) => item[prop]);
  14.   arr.push(label); //拼接内容和表头数据
  15.   const contentWidths = arr.map((item: any) => {
  16.     // console.log("item", item);
  17.     // console.log("PROP", prop);
  18.     const value = item ? String(item) : "";
  19.     const textWidth = getTextWidth(value);
  20.     return textWidth + padding;
  21.   });
  22.   // console.log("contentWidths", contentWidths);
  23.   let maxWidth = Math.max(...contentWidths);
  24.   if (maxWidth > 240) {
  25.     maxWidth = 240;
  26.   }
  27.   return Math.max(minWidth, maxWidth);
  28. }
  29. /**
  30. * el-table扩展工具  -- 列宽度自适应 - 获取列宽内文本宽度
  31. * @param {*} text 文本内容
  32. * @returns 文本宽度(int)
  33. */
  34. function getTextWidth(text: string) {
  35.   const span = document.createElement("span");
  36.   span.style.visibility = "hidden";
  37.   span.style.position = "absolute";
  38.   span.style.top = "-9999px";
  39.   span.style.whiteSpace = "nowrap";
  40.   span.innerText = text;
  41.   document.body.appendChild(span);
  42.   const width = span.offsetWidth + 5;
  43.   document.body.removeChild(span);
  44.   return width;
  45. }
复制代码
到此这篇关于vue3基于elementplus 简单实现表格二次封装过程的文章就介绍到这了,更多相关vue表格二次封装内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源:https://www.jb51.net/javascript/3211083t8.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具