您好,登錄后才能下訂單哦!
這篇文章主要介紹了怎么使用React+Ts實現二次封裝組件的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇怎么使用React+Ts實現二次封裝組件文章都會有所收獲,下面我們一起來看看吧。
若是確定了組件在項目中的整體樣式,可以寫在全局樣式中,做一個覆蓋效果。
以下的overrides.less 是Umi中專門為修改組件樣式定制的,我們通過增加id選擇器的方式加強權重來進行覆蓋默認樣式的效果。
若是有某些樣式不一致的地方,我們可以直接到組件里再進行一次覆蓋,如下所示:
同理只是又借用了組件的id進行加強權重
這樣就避免了 !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
我們使用時就可以直接傳入類型
我們想要擴展組件內的結構,可以自定義字段來控制顯示,如下的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實現二次封裝組件”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。