Vue3 基于 Element plus 对 el-pagination 进行二次封装

本文介绍了如何在Vue项目中对ElementPlus的Pagination组件进行二次封装,减少了参数传递的复杂性,同时展示了如何使用props、emits和$attrs进行组件交互,以及引入的相关技术如Sass和Eslint。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里写自定义目录标题

技术栈

框架说明版本
Vue渐进式 JavaScript 框架3.3.4
Vite前端开发与构建工具4.4.11
Element Plus基于 Vue 3,面向设计师和开发者的组件库2.4.1
Pinia符合直觉的 Vue.js 状态管理库2.1.7
vue-routerVue.js 的官方路由管理库4.2.5
SassCSS 预处理器1.69.5
VueUse基于 Vue 组合式 API 的实用工具集10.5.0
Axios用于浏览器和 Node.js 的基于 Promise 的 HTTP 请求库1.6.0
UnoCSS原子化CSS引擎0.57.2
Eslint可配置的 JavaScript 检查器8.52.0

写在前面

最近手上有个项目,刚开始开发,在开发一些列表的时候,必须会用到一些分页组件(el-pagination),用过的同学都知道,这个组件的配置参数还是比较多的,所以犹豫了一秒钟,打算自己对它进行一个二次封装

开始

在项目的 components 目录下新建一个 Pagination 文件夹,文件夹中新建一个 index.vue 文件,这里就编写组件的源代码

<script setup>
/**
 * 二次封装 el-pagination 组件,组件参数同原组件保持一致
 * 官方文档 https://element-plus.org/zh-CN/component/pagination.html
 * 抛出 change 事件,触发列表更新
 */
defineOptions({
  name: "Pagination",
});
defineProps({
  currentPage: {
    type: Number,
    default: 1,
  },
  pageSize: {
    type: Number,
    default: 10,
  },
  pageSizes: {
    type: Array,
    default: () => [10, 20, 50, 100],
  },
  layout: {
    type: String,
    default: "total, sizes, prev, pager, next, jumper",
  },
});
const emits = defineEmits(["update:currentPage", "update:pageSize", "change"]);

/**
 * page-size 每页显示条目个数改变时触发
 * @param pageSize {Number} 每页显示条目个数
 */
function sizeChange(pageSize) {
  emits("update:pageSize", pageSize);
}

/**
 * current-page 当前页数改变时触发
 * @param currentPage {Number} 当前页数
 */
function currentChange(currentPage) {
  emits("update:currentPage", currentPage);
}

/**
 * current-page 或 page-size 更改时触发
 */
function change() {
  emits("change");
}
</script>

<template>
  <el-pagination
    class="pagination"
    :layout="layout"
    :current-page="currentPage"
    :page-size="pageSize"
    :page-sizes="pageSizes"
    v-bind="$attrs"
    @change="change"
    @size-change="sizeChange"
    @current-change="currentChange"
  />
</template>

<style scoped lang="scss">
.pagination {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  margin-top: 20px;
}
</style>

这的代码量不是很多,也才七十几行,这里使用了一个 v-bind="$attrs" 这样的一个属性,它可以把外面 props 直接传递到 el-pagination 组件中

组件的使用

<script setup>
import { Search } from "@element-plus/icons-vue";

const params = ref({
  name: "",
  pageNum: 1,
  pageSize: 10,
});
const deviceTotal = ref(288);
const deviceList = ref([
  {
    id: 1,
    name: "设备1",
  },
  {
    id: 2,
    name: "设备2",
  },
  {
    id: 3,
    name: "设备3",
  },
]);

/**
 * 获取设备列表
 */
function getDeviceList() {
  console.log("获取设备列表", toRaw(params.value));
}
</script>

<template>
  <div class="app-container">
    <el-form ref="filterForm" class="form-filter" inline :model="params" @submit.prevent>
      <el-form-item label="设备名称" prop="name">
        <el-input
          v-model="params.name"
          style="width: 200px"
          placeholder="请输入设备名称"
          clearable
          @keyup.enter="getDeviceList"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" :icon="Search" @click="getDeviceList">查 询</el-button>
      </el-form-item>
    </el-form>
    <el-table stripe :data="deviceList">
      <el-table-column type="selection" width="55" />
      <el-table-column label="设备名称" prop="name" />
    </el-table>
    <pagination
      v-model:current-page="params.pageNum"
      v-model:page-size="params.pageSize"
      :total="deviceTotal"
      @change="getDeviceList"
    />
  </div>
</template>

Tips:项目中配置了 unplugin-vue-components 插件自动导入组件,所以在上面没有显示的导入,这个请注意

页面展示效果
控制台输出
使用的效果和原来的组件基本一致,这里还可以直接使用官方文档中的属性

在这里插入图片描述
在这里插入图片描述
使用 v-bind="$attrs" 可以大大减少组件二次封装带来的参数传递困扰,也可以在组件中使用 defineProps 配置来定义默认值

结束

好了,这期分享就到此结束,有更好的推荐,欢迎大家在评论区讨论

个人博客地址

### 封装 `el-pagination` 组件 为了在 Vue 3 中使用 Setup 语法糖来封装 Element Plus 的 `el-pagination` 组件,可以创建一个新的组合式 API 函数以便于重用逻辑。下面是一个具体的实现例子。 #### 创建自定义 Hook 首先,在项目中新建一个文件夹用于存放可复用的钩子函数,比如命名为 `composables` 文件夹,并在此目录下建立名为 `usePagination.js` 或者 `.ts` 的文件: ```javascript // composables/usePagination.ts import { ref, computed } from &#39;vue&#39; export function usePagination(totalPages = 10) { const currentPage = ref(1) const handleCurrentChange = (val) => { currentPage.value = val } return { currentPage, totalPages: computed(() => totalPages), handleCurrentChange } } ``` 此部分代码通过组合式API提供了分页所需的基础属性和方法[^1]。 #### 使用自定义Hook构建组件 接着可以在单文件组件(SFC)里引入并应用这个 hook 来简化模板中的逻辑处理: ```html <template> <div class="pagination-container"> <!-- 这里的 :total 和 @current-change 是 el-pagination 需要绑定的数据 --> <el-pagination background layout="prev, pager, next" :total="props.total * 10" :page-size="10" v-model:currentPage="state.currentPage" @current-change="handlePageChange"/> </div> </template> <script setup lang="ts"> import { defineProps, reactive } from &#39;vue&#39; import { usePagination } from &#39;../composables/usePagination&#39; const props = defineProps({ total: Number // 总条目数 }) let state = reactive(usePagination(props.total)) function handlePageChange(val){ console.log(`当前页: ${val}`) } </script> <style scoped> .pagination-container{ margin-top: 20px; text-align:center; } </style> ``` 上述代码展示了如何利用 `<script setup>` 结合 TypeScript 定义了一个响应式的 pagination 组件实例[state], 并将其与 template 中的 `v-model` 及事件监听器关联起来.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值