el-table简单封装 含分页

el-table简单封装 含分页

el-table组件封装代码

<template>
  <div>
    <el-table :data="form.promotionGoodsList" style="width: 100%">
      <!-- 其他需要展示的列 -->
    </el-table>
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="currentPage"
      :page-sizes="[5, 10, 20, 50]"
      :page-size="pageSize"
      :total="total"
      layout="total, sizes, prev, pager, next, jumper">
    </el-pagination>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      currentPage: 1,
      pageSize: 10,
      total: 20,
      form:{
      promotionGoodsList:[]
      },
      dataList:[]
    };
  },
  computed: {
    'form.promotionGoodsList'() {
      const start = (this.currentPage - 1) * this.pageSize;
      const end = start + this.pageSize;
      return this.dataList.slice(start, end);
    },
  },
  methods: {
    handleSizeChange(val) {
      this.pageSize = val;
      this.currentPage = 1;
    },
    handleCurrentChange(val) {
      this.currentPage = val;
    },
  },
};
</script>
<think>我们参考了引用[3]中对el-table进行二次封装的经验,以及引用[4]中关于el-table-v2的多选框封装Hook的思路。我们的目标是将el-table-v2封装成与el-table相同的使用方式,包括支持类似的列定义方式(包括插槽)分页等。 分析: 1. el-table使用template来定义列,而el-table-v2使用一个列数组(columns)来定义列,并且插槽的使用方式也不同。 2. 我们需要设计一个组件,它能够接受类似el-table的列定义(通过template)并转换为el-table-v2所需的columns数组。 3. 同时,我们还需要处理分页(参考引用[4]中的跨页多选思路)以及其他el-table的常用特性。 设计思路: 1. 使用渲染函数(render function)或作用域插槽(scoped slot)来模拟el-table的列插槽。 2. 创建一个包装组件,该组件接受类似el-table的列定义(通过插槽),然后在内部将这些列定义转换为el-table-v2的columns配置。 3. 对于分页,我们可以封装一个分页组件,并处理跨页多选(如果需要)的逻辑。 步骤: 1. 定义组件的props,包括数据源(dataSource)、列定义(columns,可选,如果使用插槽则不需要直接传入列配置)、分页配置等。 2. 使用作用域插槽来获取列定义(类似于el-table的写法),但这里我们也可以考虑使用函数式组件或渲染函数来动态生成列。 3. 在组件内部,将用户通过插槽定义的列转换为el-table-v2所需的列配置数组。 4. 处理分页逻辑,包括分页切换、跨页选择等(参考引用[4]中的设计)。 具体实现: 由于el-table-v2要求使用一个数组来定义列,我们可以这样设计: -封装组件中,我们使用一个默认插槽,允许用户像使用el-table一样定义列,例如: <template> <my-table-v2 :data="data"> <el-table-column prop="name" label="姓名" /> <el-table-column label="操作"> <template #default="scope"> <button @click="handleClick(scope.row)">操作</button> </template> </el-table-column> </my-table-v2> </template> - 在my-table-v2组件内部,我们需要遍历插槽中的el-table-column组件实例,提取出prop、label、width等信息,并且对于有插槽的列,我们需要自定义cellRenderer。 但是,在Vue3中,我们可以使用`useSlots`来获取插槽,然后动态生成列配置。 然而,el-table-v2的列配置中,自定义单元格渲染器(cellRenderer)是一个函数,我们可以在这个函数中渲染用户定义的插槽内容。 实现难点:如何将用户定义的插槽内容转换为cellRenderer函数? 解决方案: - 我们可以创建一个Vue组件来包装用户定义的插槽,然后在cellRenderer函数中使用`h`函数(createVNode)来渲染这个组件,并传递当前行数据等。 步骤: 1.封装的组件中,我们获取默认插槽(即列定义)。 2. 遍历每个列,提取属性(prop, label, width等)。 3. 对于有默认插槽的列,我们创建一个自定义的cellRenderer函数,该函数会使用一个Vue组件(比如叫做SlotRenderer)来渲染插槽内容,并将当前行的数据作为作用域插槽的参数传递进去。 示例代码(使用Vue3的Composition API): - 定义SlotRenderer组件(用于渲染插槽): const SlotRenderer = defineComponent({ props: ['row', 'column'], setup(props) { // 这里我们不需要具体的逻辑,只需要在渲染函数中返回插槽内容 }, render() { // 通过this.$slots.default 来渲染插槽,并将row作为参数传递 return this.$slots.default?.(this.row); } }); -封装的表格组件中,构建列配置: import { h, useSlots } from 'vue'; setup(props, { slots }) { const slotsData = useSlots(); const columns = []; // 遍历默认插槽中的节点(假设都是el-table-column组件) slotsData.default?.().forEach(vnode => { // 获取vnode的props(即el-table-column的prop, label, width等) const columnProps = vnode.props; const column = { key: columnProps.prop || columnProps.label, // 需要唯一标识 dataKey: columnProps.prop, title: columnProps.label, width: columnProps.width || 100, }; // 检查这个列是否有默认插槽(即自定义内容) const slotName = columnProps.prop ? `default` : undefined; // 注意:el-table-column的插槽名为default,但如果没有prop,我们可能需要特殊处理 if (vnode.children && slotName) { // 获取这个列的作用域插槽函数 const slotFn = vnode.children[slotName]; if (slotFn) { column.cellRenderer = ({ rowData }) => { // 使用SlotRenderer组件,并将插槽函数作为其子节点 return h(SlotRenderer, { row: rowData }, { default: () => slotFn({ row: rowData }) // 这里slotFn是一个函数,返回VNode数组 }); }; } } columns.push(column); }); return { columns }; } 4. 在模板中,使用el-table-v2并传入转换后的columnsdata。 注意:上述转换过程需要处理更复杂的情况,例如列可能有多个插槽(比如header插槽),但我们的目标是模拟el-table,所以主要关注default插槽。 5. 分页处理: 我们可以将分页组件独立出来,并处理跨页多选。参考引用[4]中的Hook,我们可以封装一个useSelection钩子来处理跨页选择。 6. 最终,我们封装的组件应该提供类似于el-table的API,包括事件(如row-click)属性(如height, max-height等)。 考虑到复杂度,我们可以分步骤实现,先实现基本表格展示自定义内容,再逐步添加分页、多选等功能。 示例组件结构: <template> <el-table-v2 :columns="innerColumns" :data="innerData" v-bind="otherProps" /> <!-- 分页组件 --> <el-pagination v-if="showPagination" ... /> </template> 其中,innerColumns是通过上述方法转换得到的列配置,innerData是当前页的数据(如果分页的话)。 关于数据加载: 我们可以设计一个fetchData属性(函数),当需要分页时,由组件内部调用该函数获取数据,并处理分页参数。 总结:封装的关键点在于将模板中的列定义转换为el-table-v2的列配置数组,并支持插槽的自定义渲染。同时,分页多选等功能可以借鉴已有的封装经验。 相关问题: 1.封装el-table-v2时如何处理复杂的表头(如合并表头)? 2. 如何实现跨页多选功能? 3. 如何优化el-table-v2在大数据量下的性能?</think>### 将 el-table-v2 封装el-table 使用方式 要封装 `el-table-v2` 实现类似 `el-table` 的使用方式,核心在于**设计统一的列声明接口****插槽兼容机制**。以下是实现方案: #### 1. 核心设计思路 ```tsx // 封装组件 TableWrapper.vue <template> <el-table-v2 :columns="processedColumns" :data="innerData" v-bind="attrs" > <!-- 动态生成列插槽 --> <template v-for="col in columns" #[col.slotName]="{ row }"> <slot :name="col.slotName" :row="row" /> </template> </el-table-v2> </template> <script setup> import { computed, useAttrs } from 'vue' const props = defineProps({ columns: { // 关键:兼容 el-table 的列定义方式 type: Array, default: () => [], validator: cols => cols.every(c => 'prop' in c && 'label' in c) }, dataSource: Array }) const attrs = useAttrs() const innerData = ref([]) // 转换列配置为 el-table-v2 格式 const processedColumns = computed(() => { return props.columns.map(col => ({ key: col.prop, dataKey: col.prop, title: col.label, width: col.width, // 标识插槽名称 slotName: col.slotName || `col-${col.prop}` })) }) </script> ``` #### 2. 插槽兼容方案 **使用方式对比**: ```html <!-- 原生 el-table --> <el-table :data="data"> <el-table-column prop="name" label="姓名"> <template #default="{ row }"> <a @click="handleClick(row)">{{ row.name }}</a> </template> </el-table-column> </el-table> <!-- 封装后使用 --> <TableWrapper :columns="columns" :data-source="data"> <template #col-name="{ row }"> <a @click="handleClick(row)">{{ row.name }}</a> </template> </TableWrapper> ``` #### 3. 分页与多选集成 参考引用[4]的跨页多选方案: ```ts // 分页多选Hook (useSelection.js) export function useSelection(options) { const selected = ref(new Map()) const toggleSelection = (row, page) => { const key = `${page}-${row.id}` if (selected.value.has(key)) { selected.value.delete(key) } else { selected.value.set(key, row) } } const getSelectedRows = () => [...selected.value.values()] return { selected, toggleSelection, getSelectedRows } } ``` #### 4. 完整特性支持 | 功能 | 实现方案 | |-------------------|------------------------------------------------------------------------| | 列定义 | 通过 `columns` prop 接收类 el-table-column 配置[^1] | | 作用域插槽 | 动态生成 `#col-{prop}` 格式的插槽[^2] | | 分页 | 集成 el-pagination 并处理跨页数据[^4] | | 跨页多选 | 使用 Map 存储分页标识的选中状态[^4] | | 属性透传 | 通过 `v-bind="attrs"` 传递原生 el-table-v2 属性 | | 异步数据加载 | 实现 `fetchData` 回调函数支持 | #### 5. 使用示例 ```vue <TableWrapper :columns="[ { prop: 'name', label: '姓名', slotName: 'customName' }, { prop: 'age', label: '年龄' } ]" :data-source="tableData" row-key="id" @selection-change="handleSelect" > <!-- 自定义姓名列 --> <template #customName="{ row }"> <el-tag>{{ row.name }}</el-tag> </template> </TableWrapper> ``` ### 关键技术点 1. **列配置转换器**:将 el-table 风格的列配置转换为 el-table-v2 需要的格式 2. **动态插槽映射**:根据列配置自动生成对应作用域插槽 3. **状态隔离**:使用分页标识符(`${page}-${id}`)实现跨页数据持久化 4. **属性透传**:利用 Vue 的 `useAttrs()` 实现原生属性继承 > 通过这种封装方式,开发者可以保持 el-table 的使用习惯,同时获得 el-table-v2 的虚拟滚动性能优势。实际项目中可结合引用[3]的封装经验,添加统一的样式规范预置功能模块[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sunny

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值