返回顶部
首页 > 资讯 > 前端开发 > JavaScript >React+Ts实现二次封装组件
  • 778
分享到

React+Ts实现二次封装组件

ReactTs封装组件ReactTs组件 2023-05-17 05:05:33 778人浏览 泡泡鱼
摘要

目录前言样式类型扩展功能扩展 继承 修改 拦截前言 在React中相信大家用的最多的组件库就是Antd了,可是往往在公司的实际开发过程中,我们会发现ui给的设计图和组件有着不小的差别

前言

React中相信大家用的最多的组件库就是Antd了,可是往往在公司的实际开发过程中,我们会发现ui给的设计图和组件有着不小的差别,不管是在样式上还是功能上。并且可能存在根据项目主题定制的风格,那我们最好是不要一个个的去使用antd里的组件,然后再去修改其内部样式和功能扩展或修改,这样不管是从效率还是维护性都不是理想的。那如何优雅的对现有的组件库进行二次封装就是我们今天探讨的主要内容了,以下做法有不足之处望各位大佬不吝赐教。

ps:项目演示采用 react18+umi4+antd5+ts

样式

若是确定了组件在项目中的整体样式,可以写在全局样式中,做一个覆盖效果。
以下的overrides.less 是Umi中专门为修改组件样式定制的,我们通过增加id选择器的方式加强权重来进行覆盖默认样式的效果。

image.png

若是有某些样式不一致的地方,我们可以直接到组件里再进行一次覆盖,如下所示:
同理只是又借用了组件的id进行加强权重

image.png

这样就避免了 !import的普遍存在了

类型扩展

我们可能会遇到组件依赖外部类型来决定内部类型的情况,就比如表格组件中列表的数据类型肯定是不一样的,那我们就需要通过泛型让外面传递进来。从而达到规范的效果。

import type { PaginationProps } from 'antd'
import { Table } from 'antd'
import type { TableProps } from 'antd/es/table'
import {
  FilterValue,
  RowSelectMethod,
  SorterResult,
  TableCurrentDataSource,
  TablePaginationConfig,
  TableRowSelection,
} from 'antd/es/table/interface'
import { ForwardedRef, forwardRef, Key, useCallback, useImperativeHandle, useMemo, useState } from 'react'
import styles from './index.less'

// 处理forwardRef使其可以接受泛型
declare module 'react' {
  // eslint-disable-next-line @typescript-eslint/ban-types
  function forwardRef<T, P = {}>(
    render: (props: P, ref: React.Ref<T>) => React.ReactElement | null
  ): (props: P & React.RefAttributes<T>) => React.ReactElement | null
}

export type onChangeType<RecordType> = (
  pagination: TablePaginationConfig,
  filters: Record<string, FilterValue | null>,
  sorter: SorterResult<RecordType> | SorterResult<RecordType>[],
  extra: TableCurrentDataSource<RecordType>
) => void

export type onSelectChangeType<T> = (
  selectedRowKeys: Key[],
  selectedRows: T[],
  info: {
    type: RowSelectMethod
  }
) => void

interface TProps<T> extends React.PropsWithChildren<TableProps<T>> {
  tableData?: pagingResProps<T> // 总数据
  tableOnChange?: onChangeType<T> // 变化回调
  tableRowSelection?: TableRowSelection<T> // 自定义行数据设置
  tablePagination?: TablePaginationConfig //自定义分页配置
  bottomTitleFlag?: boolean // 左下页角信息是否显示
}

// table ref的参数
export interface TableDefaultRefProps<T> {
  selectedRowKeys: Key[]
  selectedRowRows: T[]
}

const _TableDefault = <T extends object>(props: TProps<T>, ref: ForwardedRef<TableDefaultRefProps<T>>) => {
  return <div>table</div>
}

const TableDefault = forwardRef(_TableDefault)
export default TableDefault

我们使用时就可以直接传入类型

image.png

功能扩展 继承 修改 拦截

我们想要扩展组件内的结构,可以自定义字段来控制显示,如下的bottomTitleFlag,就是控制标题的展示。

我们可以通过...otherProps的方式接收剩余参数,从而实现了可以在我们的组件上传递antd规定的组件属性,若是相同则会进行覆盖采用新传入的。若是我们不传递则采用内置的,若是内置的还不满足需求,我们可以在内置里再加上剩余参数的写法进行补充如 ...tablePagination。

事件需要拦截可以内置一个事件,然后通过调用内置事件时进行数据相关处理后再去调传入的事件,这样就实现拦截的效果了。

另外对于外界可能会用的的一些参数我们可以通过 useImperativeHandle 进行Ref抛出,使得更好去获取内部的属性。

const _TableDefault = <T extends object>(props: TProps<T>, ref: ForwardedRef<TableDefaultRefProps<T>>) => {
  const { tableData, tableOnChange, tableRowSelection, tablePagination, bottomTitleFlag = false, ...otherProps } = props

  // 当前选择的key和行
  const [selectedRowKeys, setSelectedRowKeys] = useState<Key[]>([])
  const [selectedRowRows, setSelectedRowRows] = useState<T[]>([])

  // 左右分页样式处理
  const itemRender: PaginationProps['itemRender'] = (_, type, originalElement) => {
    if (type === 'prev') {
      return <a style={{ color: '#CCF2FF', fontSize: '14px' }}>上一页</a>
    }
    if (type === 'next') {
      return <a style={{ color: '#CCF2FF', fontSize: '14px' }}>下一页</a>
    }
    return originalElement
  }

  const handelChange: onChangeType<T> = useCallback((pagination, filters, sorter, extra) => {
    // 想要做的拦截操作
    props.tableOnChange?.(pagination, filters, sorter, extra)
  }, [])

  // 选择多选框回调
  const onSelectChange: onSelectChangeType<T> = (selectedRowKeys, selectedRows, info) => {
    setSelectedRowKeys(selectedRowKeys)
    setSelectedRowRows(selectedRows)
  }

  // ref抛出变量
  useImperativeHandle(ref, () => ({
    selectedRowKeys,
    selectedRowRows,
  }))
  // 开始页码
  const startCode = useMemo(
    () => () => {
      if (!tableData || !tableData?.current) return 1
      return (tableData?.current - 1) * tableData?.size + 1
    },
    [tableData]
  )
  // 结束页码
  const endCode = useMemo(
    () => () => {
      if (!tableData) return 99
      return Math.min(tableData?.total, tableData?.current * tableData?.size)
    },
    [tableData]
  )
  return (
    <div
      className={styles.tableDefault}
      id="tableDefault"
    >
      <Table
        rowKey="id"
        dataSource={tableData?.records}
        pagination={{
          itemRender,
          total: tableData?.total,
          showSizeChanger: false,
          pageSize: tableData?.size,
          current: tableData?.current,
          ...tablePagination,
        }}
        onChange={handelChange}
        rowSelection={{
          type: 'checkbox',
          fixed: false,
          columnWidth: '120px',
          selectedRowKeys,
          onChange: onSelectChange,
          ...tableRowSelection,
        }}
        {...otherProps}
      />
      <div className={styles.leftIcon}></div>
      {bottomTitleFlag && (
        <div className={styles.bottomTitle}>{`显示第${startCode()}到第${endCode()}条记录,总共${
          tableData?.total
        }条记录`}</div>
      )}
    </div>
  )
}

const TableDefault = forwardRef(_TableDefault)
export default TableDefault

我们想要扩展组件内的功能,增加内置功能可以直接在组件内部增加,使用内部数据来完成,最后进行一个抛出。
这里使用 node[fieldNames.key] 计算属性名的原因是树组件的字段可能会发生变化,所以我们需要根据传入的fieldNames来进行字段更新。

树组件

// 当前节点展开
  function nowNodeExpand(node: DataNode) {
    const newExpandedKeys: any[] = []
    const fn = (node: any) => {
      node[fieldNames.key] && newExpandedKeys.push(node[fieldNames.key])
      node[fieldNames.children] && node[fieldNames.children].forEach((item: DataNode) => fn(item))
    }
    fn(node)
    setExpandedKeys(uniq([...expandedKeys, ...newExpandedKeys]))
  }
  
  // ref抛出变量
  useImperativeHandle(ref, () => ({
    nowNodeExpand,
  }))

到此这篇关于React+Ts实现二次封装组件的文章就介绍到这了,更多相关React Ts封装组件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: React+Ts实现二次封装组件

本文链接: https://lsjlt.com/news/210727.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • React+Ts实现二次封装组件
    目录前言样式类型扩展功能扩展 继承 修改 拦截前言 在react中相信大家用的最多的组件库就是Antd了,可是往往在公司的实际开发过程中,我们会发现ui给的设计图和组件有着不小的差别...
    99+
    2023-05-17
    React Ts封装组件 React Ts组件
  • Vue3+Vite+TS实现二次封装element-plus业务组件sfasga
    目录1.结构字符串2.返回tuple元组3.访问Dict字典4.运用库5.在列表中切片/步进 6.用 ranges 1.结构字符串 你会经常需求打印字符串。要是有很多变量,防止下面这...
    99+
    2024-04-02
  • React组件二次包装的具体实现
    目录1. 类型声明2. 默认属性3. 自定义属性与属性透传原生组件是对公共场景的抽象,若要契合实际业务往往需要对其进行二次包装。对组件进行二次包装一般需要进行包括不限于以下的步骤: ...
    99+
    2024-04-02
  • jsoneditor二次封装实时预览json编辑器组件react版
    目录前言设计思路正文jsoneditor的使用结合react进行二次封装前言 做为一名前端开发人员,掌握vue/react/angular等框架已经是必不可少的技能了,我们都知道,v...
    99+
    2022-11-13
    jsoneditor二次封装json编辑器 jsoneditor 实时预览编辑器
  • react+ ts vite搭建及二次封装请求的过程解析
    目录1.搭建项目2.下载axios3.创建http文件夹下index.ts1.搭建项目 npm create vite 2.下载axios npm install axios 打...
    99+
    2023-05-17
    react二次封装请求 react ts vite请求
  • Element怎么使用el-table组件实现二次封装
    这篇文章主要讲解了“Element怎么使用el-table组件实现二次封装”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Element怎么使用el-table组件实现二次封装”吧!一、安装引...
    99+
    2023-07-02
  • Element使用el-table组件二次封装
    目录前言一、安装引入二、封装功能三、样式覆盖四、使用组件前言 在vue开发中使用element-ui的el-table时一般都需要进行封装以便于复用,提高开发效率,减少重复代码,这篇...
    99+
    2024-04-02
  • 四、axios在vite+ts使用class类二次封装
    文章目录 前言aioxs二次封装配置报错element plus弹框引入不识别 还需要引入到同时从fig.json使用 总结 前言 aioxs二次封装配置 引入需要的文件创建...
    99+
    2023-09-08
    javascript 前端 开发语言 vue.js typescript 前端框架
  • Flutter 极简 Dio 组件二次封装文档
    Flutter Dio 组件二次封装文档 前言一、添加依赖二、创建封装类三、使用封装类四、拦截器五、错误处理总结 前言 本文档介绍了如何通过二次封装 Flutter Dio 组件来简化网络请求的过程。通过封装,我们可以提高代码...
    99+
    2023-08-17
    flutter android
  • Vue组件二次封装的实用技巧是什么
    这篇文章主要讲解了“Vue组件二次封装的实用技巧是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue组件二次封装的实用技巧是什么”吧!透传 Attribute我们可以使用一个没有参数的...
    99+
    2023-06-30
  • vue如何实现axios二次封装
    这篇文章主要介绍“vue如何实现axios二次封装”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vue如何实现axios二次封装”文章能帮助大家解决问题。axiosaxios 是一个基于 promi...
    99+
    2023-07-04
  • 基于React封装组件的实现步骤
    目录前言antd 是如何封装组件的divider 组件源代码如何暴露组件属性如何设置统一类名前缀如何处理样式与类名divider 组件样式源代码前言 很多小伙伴在第一次尝试封装组件时...
    99+
    2024-04-02
  • 从零搭建react+ts组件库(封装antd)的详细过程
    目录整体需求开发与打包工具选型使用webpack作为打包工具使用babel来处理typescript代码使用less-loader、css-loader等处理样式代码项目搭建思路整体...
    99+
    2024-04-02
  • Vue中图片上传组件封装-antd的a-upload二次封装的实例
    目录图片上传组件封装-antd的a-upload二次封装api组件封装使用优化图片上传组件封装-antd的a-upload二次封装 a-upload组件 api const pub...
    99+
    2024-04-02
  • Vue组件二次封装的一些实用技巧总结
    目录前言透传 Attribute透传 slot普通slot动态插槽名作用域插槽封装组件存在的问题组件实例属性和方法的调用总结前言 在开发Vue项目我们一般使用第三方UI组件库进行开发...
    99+
    2024-04-02
  • vue如何实现axios的二次封装
    这篇文章主要介绍“vue如何实现axios的二次封装”,在日常操作中,相信很多人在vue如何实现axios的二次封装问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”vue如何实现axios的二次封装”的疑惑有所...
    99+
    2023-07-04
  • React+ts实现二级联动效果
    本文实例为大家分享了React+ts实现二级联动效果的具体代码,供大家参考,具体内容如下 .tsx文件 import { Component, createRef} from 're...
    99+
    2024-04-02
  • vue3.0 移动端二次封装van-uploader实现上传图片(vant组件库)
    1、前提:业务需求,最多上传6张图片,并可以实现本地预览 2、解决方法:使用vant组件库中的van-uploader实现 3、代码实现 template <div cl...
    99+
    2024-04-02
  • React怎么封装SvgIcon组件
    本篇内容介绍了“React怎么封装SvgIcon组件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!React优雅的封装SvgIcon组件相信...
    99+
    2023-07-05
  • 关于ElementUI的el-upload组件二次封装的问题
    目录ElementUI的el-upload组件二次封装问题组件使用el-upload组件封装后更好用了组件截图组件代码部分ElementUI的el-upload组件二次封装问题 开发...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作