当前位置: 首页 > article >正文

二次封装 el-pagination 组件存在的问题

在使用 Element Plus 组件时,有时会遇到组件不完全符合需求的情况,这时可能需要对其进行二次封装。在封装 Pagination 组件时,我们会发现一些属性和函数无法正常使用,下面将详细探讨这些问题,并提供一下思路和想法。

封装组件代码如下:

import { ElPagination } from 'element-plus';
import './index.less';

export default defineComponent({
  name: 'MyPagination',
  props: paginationProps,
  setup(props, { attrs, slots }) {
    return () => (
      <div class={`pagination-common`}>
        <ElPagination
          {...props}
          {...attrs}
        >
          {slots.default ? slots.default() : null}
        </ElPagination>
      </div>
    );
  },
});

1. 属性

1.1 pageSize 属性

在使用自定义 MyPagination 组件时:

import { defineComponent, ref } from "vue";
import { MyPagination } from "../MyPagination";
import "./index.less";

export default defineComponent({
  name: "Demo",
  setup() {
    return () => (
      <div class="paginationContainer">
        <MyPagination
          layout="total, sizes, prev, pager, next, jumper"
          total={500}
          pageSize={20}
        />
      </div>
    );
  }
});

代码警告⚠️:

简单分析一下,可以看到是 pageSize 出现问题导致的报错,为什么呢?

对于 Element Plus 的 Pagination 组件而言,pageSize 是一个受控属性,也就是需要外部管理它的值并对变动进行响应。

那该属性应该怎么使用呢?

import { defineComponent, ref } from "vue";
import { MyPagination } from "../MyPagination";
import "./index.less";

export default defineComponent({
  name: "Demo",
  setup() {
    const pageSize = ref(30);
    return () => (
      <div class="paginationContainer">
        <MyPagination
          layout="total, sizes, prev, pager, next, jumper"
          total={500}
          v-model:pageSize={pageSize.value}
        />
      </div>
    );
  }
});

成功展示的原因:

1、双向绑定机制

使用 v-model 实现双向绑定,确保组件内的 pageSize 更新会自动反映到外部的数据(pageSizeRef),从而保持组件和外部状态的一致。

2、事件触发更新

Pagination 组件内部会触发 update:pageSize 事件来通知外部其 pageSize 的改变。使用 v-model:pageSize 可以自动捕获并处理这个事件,避免手动监听 update:pageSize 事件。

1.2 currentPage 属性

同理 currentPage 表示当前的页码,也是受控属性,需要绑定 v-model。当用户点击分页控件来切换页码时,Pagination 组件 会触发 update:currentPage 事件更新外部的 currentPage 绑定的变量。

使用如下:

import { defineComponent, ref } from "vue";
import { MyPagination } from "../MyPagination";
import "./index.less";

export default defineComponent({
  name: "Demo",
  setup() {
    const currentPage = ref(3);
    const pageSize = ref(30);
    return () => (
      <div class="paginationContainer">
        <MyPagination
          layout="total, sizes, prev, pager, next, jumper"
          total={500}
          v-model:pageSize={pageSize.value}
          v-model:currentPage ={currentPage.value}
        />
      </div>
    );
  }
});

1.3 total 属性

total 表示数据总数,也是受控属性。

虽然 total 本身不需要 v-mode(因为其通常是只读属性,用于展示总数据量),但在某些场景下会根据后端返回数据动态更新,因此不使用 v-model 绑定的情况较多。

2. 方法

大家如果使用过这个组件,肯定了解其身上存在 4 个常见方法,其中,唯一能够正常使用的方法是 currentChange,而其他方法则需要额外处理才能执行。感兴趣的朋友可以亲自尝试一下,这里就不详细介绍啦。

解决方法,我们点开 Pagination 组件 props 的源码可以看到方法的名称:

因此在使用的时候,严格遵循命名规则,如下:

import { defineComponent, ref } from "vue";
import { MyPagination } from "../MyPagination";
import "./index.less";

export default defineComponent({
  name: "Demo",
  setup() {
    const currentPage = ref(3);
    const pageSize = ref(30);
    const handleCurrentChange = (val) => {
      console.log(`当前页码已变更,新的页码为:${val} 页`);
    };
    const handleSizeChange = (size) => {
      console.log(`每页显示的条数已变更,新的条数为:${size} 条`);
    };
    const handlePrevClick = (page) => {
      console.log(`点击上一页按钮,点击之前页码为:${page} 页`);
    };
    const handleNextClick = (page) => {
      console.log(`点击下一页按钮,点击之前页码为:${page} 页`);
    };
    return () => (
      <div class="paginationContainer">
        <MyPagination
          layout="total, sizes, prev, pager, next, jumper"
          total={500}
          v-model:pageSize={pageSize.value}
          v-model:currentPage ={currentPage.value}
          onCurrent-change={handleCurrentChange}
          onSize-change={handleSizeChange}
          onPrev-click={handlePrevClick}
          onNext-click={handleNextClick}
        />
      </div>
    );
  }
});

所有的方法均可以成功使用:

如果到目前为止仍然存在一些问题,那么我们就需要使用 emits 来更新数据。

添加如下代码:

import { ElPagination } from 'element-plus';
import './index.less';

export default defineComponent({
  name: 'MyPagination',
  props: paginationProps,
  emits: [
    "update:prevClick",
    "update:nextClick",
    "currentChange",
    "update:sizeChange",
  ],
  setup(props, { attrs, slots }) {
    return () => (
      <div class={`pagination-common`}>
        <ElPagination
          {...props}
          {...attrs}
        >
          {slots.default ? slots.default() : null}
        </ElPagination>
      </div>
    );
  },
});

emits 用于声明组件可以发出的自定义事件。这使得父组件能够监听这些事件,并对其作出响应。通过声明 emits 可以清晰地定义组件的外部接口。

至此,已经解决了我在封装 Pagination 组件所遇到的问题,如果还有其他的问题,可以继续深入探讨。


http://www.kler.cn/a/382103.html

相关文章:

  • Mac使用记事
  • JAVA基础:多重循环、方法、递归 (习题笔记)
  • 看到你还在用Maven,Gradle难道不香吗?
  • 霍尼韦尔测厚仪51000372怎么工作
  • stm32 挂死定位(死循环)
  • 【LeetCode】【算法】160.相交链表
  • 微信小程序寓言童话创作APP设计与实现
  • mysql error:1449权限问题 及 用户授权
  • 备战百天,准备机考【机考笔记】
  • Spring MVC 入门案例:开启 Web 开发之旅
  • http-server:Node.js下的轻量级静态服务器工具
  • SpringBoot配置Rabbit中的MessageConverter对象
  • 【spark面试题】RDD和DataFrame以及DataSet有什么异同
  • 链表-单链表
  • [MySQL]DCL语句
  • 【UML】- 用例图(结合银行案例解释其中的奥义)
  • 蓝桥杯专项---一维前缀/差分巩固题目
  • 【5.9】指针算法-双指针解验证回文字符串 Ⅱ
  • PostgreSQL 学习笔记:PostgreSQL 主从复制
  • 【自用】fastapi教程第三节--响应与响应体