前端如何修改组件库源码来封装符合自己需求的组件

来自:掘金,作者:Huup_We
链接:https://juejin.cn/post/6917771825808146446

场景

前端开发的同学可能会遇到过这样的问题: 产品找那个需要实现某项功能,常用的elementui,antd组件库中确实有差不多功能的组件 但实际上这些组件可能并不能满足你的功能,或多或少都需要修改才能满足需求

关于组件库可能要修改的地方,我将它们分为以下五类可供参考

  • 样式问题
  • 组件暴露的参数和方法不充分 但是源码中存在
  • 可利用部分功能 但其余功能需要自己开发封装
  • 两个及以上的组件之间有联动
  • 完全没有符合的组件

分析和解决

组件样式问题

当修改单个文件的样式时,以 less 为例,如果你想要修改组件的样式,可以使用 /deep/ 或 >>> 来深度选择到你要修改的样式(这能够帮你省去一大串的类名)

.dialog-wrapper {
    /deep/.el-dialog__body{
     border: solid 1px #999;
    }
}

如果你要修改全局的样式,第一种方法,你可以在全局样式文件中写样式覆盖,引入到 main.js 中即可全局生效。如下

import "./assets/css/index.css";

如果是修改antd 可以使用:global(.className)的语法去修改组件库的样式

.wrap {
    :global(.ant-modal-body) {
        padding-top: 0;

        & > div {
            margin: 0 -24px;
            max-height: 680px !important;
        }
    }
}

组件库的组件暴露的参数和方法不充分

当我们想要获取组件的一个参数,首先是看文档中提供了哪些 Attributes、Events、Methods。如果符合需求,直接拿来用就好。如果没有你要的属性和方法,请你先去看看源码中提供了哪些东西没有向外暴露出来的,但是我们能拿来用的
以elementui的cascader级联选择器举例,我想要在选中一个搜索的选项后不关闭看板。我在组件的 Events、Methods中没有找到相关的方法控制看板展开,但当我去 github 上看该组件的源码时,我发现 toggleDropDownVisible() 方法是控制看板展开的。于是我在外部用 $refs 直接调用组件里的这个方法就好了

el-cascader
    ref="cascader" // ref获取组件
    placeholder="试试搜索:指南"
    :options="options"
    :props="{ multiple: true }"
    filterable></el-cascader
    @visible-change="$refs.cascader.toggleDropDownVisible(true)"> // 调用组件及其方法

可利用部分功能,其余功能要自己开发封装

当要用到一个组件,但从头开发这个组件既复杂又耗时,而组件库中这个组件需要再往上加一些功能就能为你所用时,你可以考虑把组件库的代码拿到自己本地,修改它

两个及以上的组件之间的联动

其实场景有很多,例如将「Form 表单」、「Table 表格」和「Pagination 分页」结合起来,封装成一个组件,这样在多表格的项目中直接使用就好了;将 table 和 pagination 放到一个组件中:

<template lang="pug">
div
  .el-table
    template(v-for="(item, index) in columns")
      el-table-column(
        :prop="item.prop"
        :key="index"
        :label="item.label")

  el-pagination.pg-wrapper(
    layout="total, sizes, prev, pager, next, jumper"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="[10, 20, 50, 100]"
    :page-size="pagesize"
    :total="total")
</template>

需要传入的参数如下:列信息 columns、单页数据量 pagesize、当前页码 currentPage、表格数据 tableData、数据总数 total、表单查询的参数 query 等

props: {
  // 列信息
  columns: {
    type: Array,
    default: [],
  }
  // 单页数据量
  pagesize: {
    type: Number,
    default: 10,
  },
  // 当前页码
  currentPage: {
    type: Number,
    default: 1,
  },
  // 表格数据
  tableData: {
    type: Array,
    default: [],
  },
  // 数据总数
  total: {
    type: Number,
    default: 1000,
  },
  // 获取数据的接口
  fetch:{
     type: function,
     default:() => {}
  },
  // 表单查询的参数
  query:{
    type: Object,
    default: () => {}
  }
},
methods: {
  // 改变当前页码 currentPage 时触发
  handleCurrentChange: function (currentPage) {
    this.$emit('handleChange', this.pagesize, currentPage)
    this.fetch(this.query)
  },
  // 改变当前页 pageSize 时触发
  handleSizeChange: function (pageSize) {
    this.$emit('handleChange', pageSize, this.currentPage)
    this.fetch(this.query)
  }
}

完全没有符合的组件

如果你要的组件,外部的组件库中都没有提供,那就自己动手封装一个。尽可能将你的组件变得通用,兼容。尝试想一想你的组件是否在其他情况下也能用。另外也可以多看看别人是如何封装组件的,这有助于你自己开发。

如果你可以将你在前端开发道路上自己封装的组件一个个收集起来,大概率可以方便你以后相同场景下直接复用,也有助于你的代码解耦

原文地址:https://www.cnblogs.com/hanyan99/p/14609620.html