最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React+Ts實(shí)現(xiàn)二次封裝組件

 更新時(shí)間:2023年04月23日 08:37:04   作者:vs心動(dòng)  
本文主要介紹了React+Ts實(shí)現(xiàn)二次封裝組件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

在react中相信大家用的最多的組件庫就是Antd了,可是往往在公司的實(shí)際開發(fā)過程中,我們會發(fā)現(xiàn)ui給的設(shè)計(jì)圖和組件有著不小的差別,不管是在樣式上還是功能上。并且可能存在根據(jù)項(xiàng)目主題定制的風(fēng)格,那我們最好是不要一個(gè)個(gè)的去使用antd里的組件,然后再去修改其內(nèi)部樣式和功能擴(kuò)展或修改,這樣不管是從效率還是維護(hù)性都不是理想的。那如何優(yōu)雅的對現(xiàn)有的組件庫進(jìn)行二次封裝就是我們今天探討的主要內(nèi)容了,以下做法有不足之處望各位大佬不吝賜教。

ps:項(xiàng)目演示采用 react18+umi4+antd5+ts

樣式

若是確定了組件在項(xiàng)目中的整體樣式,可以寫在全局樣式中,做一個(gè)覆蓋效果。
以下的overrides.less 是Umi中專門為修改組件樣式定制的,我們通過增加id選擇器的方式加強(qiáng)權(quán)重來進(jìn)行覆蓋默認(rèn)樣式的效果。

image.png

若是有某些樣式不一致的地方,我們可以直接到組件里再進(jìn)行一次覆蓋,如下所示:
同理只是又借用了組件的id進(jìn)行加強(qiáng)權(quán)重

image.png

這樣就避免了 !import的普遍存在了

類型擴(kuò)展

我們可能會遇到組件依賴外部類型來決定內(nèi)部類型的情況,就比如表格組件中列表的數(shù)據(jù)類型肯定是不一樣的,那我們就需要通過泛型讓外面?zhèn)鬟f進(jìn)來。從而達(dá)到規(guī)范的效果。

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> // 總數(shù)據(jù)
  tableOnChange?: onChangeType<T> // 變化回調(diào)
  tableRowSelection?: TableRowSelection<T> // 自定義行數(shù)據(jù)設(shè)置
  tablePagination?: TablePaginationConfig //自定義分頁配置
  bottomTitleFlag?: boolean // 左下頁角信息是否顯示
}

// table ref的參數(shù)
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

我們使用時(shí)就可以直接傳入類型

image.png

功能擴(kuò)展 繼承 修改 攔截

我們想要擴(kuò)展組件內(nèi)的結(jié)構(gòu),可以自定義字段來控制顯示,如下的bottomTitleFlag,就是控制標(biāo)題的展示。

我們可以通過...otherProps的方式接收剩余參數(shù),從而實(shí)現(xiàn)了可以在我們的組件上傳遞antd規(guī)定的組件屬性,若是相同則會進(jìn)行覆蓋采用新傳入的。若是我們不傳遞則采用內(nèi)置的,若是內(nèi)置的還不滿足需求,我們可以在內(nèi)置里再加上剩余參數(shù)的寫法進(jìn)行補(bǔ)充如 ...tablePagination。

事件需要攔截可以內(nèi)置一個(gè)事件,然后通過調(diào)用內(nèi)置事件時(shí)進(jìn)行數(shù)據(jù)相關(guān)處理后再去調(diào)傳入的事件,這樣就實(shí)現(xiàn)攔截的效果了。

另外對于外界可能會用的的一些參數(shù)我們可以通過 useImperativeHandle 進(jìn)行Ref拋出,使得更好去獲取內(nèi)部的屬性。

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

  // 當(dāng)前選擇的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)
  }, [])

  // 選擇多選框回調(diào)
  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]
  )
  // 結(jié)束頁碼
  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

我們想要擴(kuò)展組件內(nèi)的功能,增加內(nèi)置功能可以直接在組件內(nèi)部增加,使用內(nèi)部數(shù)據(jù)來完成,最后進(jìn)行一個(gè)拋出。
這里使用 node[fieldNames.key] 計(jì)算屬性名的原因是樹組件的字段可能會發(fā)生變化,所以我們需要根據(jù)傳入的fieldNames來進(jìn)行字段更新。

樹組件

// 當(dāng)前節(jié)點(diǎn)展開
  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,
  }))

到此這篇關(guān)于React+Ts實(shí)現(xiàn)二次封裝組件的文章就介紹到這了,更多相關(guān)React Ts封裝組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React中實(shí)現(xiàn)防抖功能的兩種方式小結(jié)

    React中實(shí)現(xiàn)防抖功能的兩種方式小結(jié)

    這篇文章主要介紹了React中實(shí)現(xiàn)防抖功能的兩種方式小結(jié),具有很好的 參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • React?Virtual?DOM前端框架全面分析

    React?Virtual?DOM前端框架全面分析

    這篇文章主要為大家介紹了React?Virtual?DOM前端框架全面分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • react antd-design Select全選功能實(shí)例

    react antd-design Select全選功能實(shí)例

    這篇文章主要介紹了react antd-design Select全選功能實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • React?redux?原理及使用詳解

    React?redux?原理及使用詳解

    這篇文章主要為大家介紹了React?redux?原理及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 利用CDN加速react webpack打包后的文件詳解

    利用CDN加速react webpack打包后的文件詳解

    下面小編就為大家分享一篇利用CDN加速react webpack打包后的文件詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • React?18中的state概念與使用、注意問題解決

    React?18中的state概念與使用、注意問題解決

    state和props類似,都是一種存儲屬性的方式,但是不同點(diǎn)在于state只屬于當(dāng)前組件,其他組件無法訪問,這篇文章主要介紹了React?18中的state概念與使用、注意問題,需要的朋友可以參考下
    2022-12-12
  • 使用React組件編寫溫度顯示器

    使用React組件編寫溫度顯示器

    這篇文章主要為大家詳細(xì)介紹了使用React組件編寫溫度顯示器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • redux功能強(qiáng)大的Middleware中間件使用學(xué)習(xí)

    redux功能強(qiáng)大的Middleware中間件使用學(xué)習(xí)

    這篇文章主要為大家介紹了redux功能強(qiáng)大的Middleware中間件使用學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • react-redux的connect示例詳解

    react-redux的connect示例詳解

    connect()是react-redux中的核心方法之一,它將react組件預(yù)redux中的Store真正連接在一起,這篇文章主要介紹了react-redux的connect詳解,需要的朋友可以參考下
    2023-01-01
  • React Fiber中面試官最關(guān)心的技術(shù)話題

    React Fiber中面試官最關(guān)心的技術(shù)話題

    這篇文章主要為大家介紹了React Fiber中面試官最關(guān)心的技術(shù)話題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06

最新評論

崇阳县| 万州区| 泾源县| 平顶山市| 固阳县| 内乡县| 泌阳县| 红原县| 晋城| 潼南县| 吉安市| 措勤县| 平乡县| 隆子县| 滨海县| 全椒县| 盐山县| 石棉县| 十堰市| 偃师市| 格尔木市| 广安市| 桃园市| 宁陕县| 庆元县| 徐水县| 于都县| 赞皇县| 上林县| 北京市| 东台市| 晋城| 正安县| 社会| 漯河市| 青神县| 四川省| 大方县| 宣汉县| 鄂尔多斯市| 黎川县|