当前位置: 代码迷 >> 综合 >> Ant-design 源码分析之数据展示(六)Collapse
  详细解决方案

Ant-design 源码分析之数据展示(六)Collapse

热度:23   发布时间:2023-11-19 18:18:57.0

Ant-design 源码分析之数据展示(六)Collapse

2021SC@SDUSC

一、组件结构

1、ant代码结构
在这里插入图片描述
2、组件结构

ant中Collapse的index.tsx中引入了Collapse和CollapsePanel。
引用rc-collapse。

二、antd组件调用关系

1、Collapse.tsx
导入相应模块以及相应的ICON图标

import * as React from 'react';
import RcCollapse from 'rc-collapse';
import {
     CSSMotionProps } from 'rc-motion';
import classNames from 'classnames';
import RightOutlined from '@ant-design/icons/RightOutlined';import toArray from 'rc-util/lib/Children/toArray';
import omit from 'rc-util/lib/omit';
import CollapsePanel, {
     CollapsibleType } from './CollapsePanel';
import {
     ConfigContext } from '../config-provider';
import collapseMotion from '../_util/motion';
import {
     cloneElement } from '../_util/reactNode';

声明CollapseProps接口

export type ExpandIconPosition = 'left' | 'right' | undefined;export interface CollapseProps {
    activeKey?: Array<string | number> | string | number;defaultActiveKey?: Array<string | number> | string | number;accordion?: boolean;destroyInactivePanel?: boolean;onChange?: (key: string | string[]) => void;style?: React.CSSProperties;className?: string;bordered?: boolean;prefixCls?: string;expandIcon?: (panelProps: PanelProps) => React.ReactNode;expandIconPosition?: ExpandIconPosition;ghost?: boolean;collapsible?: CollapsibleType;
}

accordion:手风琴模式,每次只打开一个tab,类型为boolean
activeKey:当前激活 tab 面板的 key,类型为string[] | string number[] | number
bordered:带边框风格的折叠面板,类型为boolean
collapsible:所有子面板是否可折叠或指定可折叠触发区域,类型为header | disabled
defaultActiveKey:初始化选中面板的 key,类型为string[] | string number[] | number
destroyInactivePanel:销毁折叠隐藏的面板,类型为boolean
expandIcon:自定义切换图标,类型为(panelProps) => ReactNode
expandIconPosition:设置图标位置,类型为left | right
ghost:使折叠面板透明且无边框,类型为boolean
onChange:切换面板的回调,类型为function

interface PanelProps {
    isActive?: boolean;header?: React.ReactNode;className?: string;style?: React.CSSProperties;showArrow?: boolean;forceRender?: boolean;/** @deprecated Use `collapsible="disabled"` instead */disabled?: boolean;extra?: React.ReactNode;collapsible?: CollapsibleType;
}interface CollapseInterface extends React.FC<CollapseProps> {
    Panel: typeof CollapsePanel;
}
const Collapse: CollapseInterface = props => {
    const {
     getPrefixCls, direction } = React.useContext(ConfigContext);const {
     prefixCls: customizePrefixCls, className = '', bordered = true, ghost } = props;const prefixCls = getPrefixCls('collapse', customizePrefixCls);
//获取图片位置const getIconPosition = () => {
    const {
     expandIconPosition } = props;if (expandIconPosition !== undefined) {
    return expandIconPosition;}return direction === 'rtl' ? 'right' : 'left';};

自定义切换图标

  const renderExpandIcon = (panelProps: PanelProps = {
     }) => {
    const {
     expandIcon } = props;const icon = (expandIcon ? (expandIcon(panelProps)) : (<RightOutlined rotate={
    panelProps.isActive ? 90 : undefined} />)) as React.ReactNode;return cloneElement(icon, () => ({
    className: classNames((icon as any).props.className, `${
      prefixCls}-arrow`),}));};
  const iconPosition = getIconPosition();const collapseClassName = classNames({
    [`${
      prefixCls}-borderless`]: !bordered,[`${
      prefixCls}-icon-position-${
      iconPosition}`]: true,[`${
      prefixCls}-rtl`]: direction === 'rtl',[`${
      prefixCls}-ghost`]: !!ghost,},className,);const openMotion: CSSMotionProps = {
    ...collapseMotion,motionAppear: false,leavedClassName: `${
      prefixCls}-content-hidden`,};

获取默认折叠面板

  const getItems = () => {
    const {
     children } = props;return toArray(children).map((child: React.ReactElement, index: number) => {
    if (child.props?.disabled) {
    const key = child.key || String(index);const {
     disabled, collapsible } = child.props;const childProps: CollapseProps & {
     key: React.Key } = {
    ...omit(child.props, ['disabled']),key,collapsible: collapsible ?? (disabled ? 'disabled' : undefined),};return cloneElement(child, childProps);}return child;});};return (<RcCollapseopenMotion={
    openMotion}{
    ...props}expandIcon={
    renderExpandIcon}prefixCls={
    prefixCls}className={
    collapseClassName}>{
    getItems()}</RcCollapse>);
};

2、CollapsePanel.tsx
导入相应模块以及相应的ICON图标

import * as React from 'react';
import RcCollapse from 'rc-collapse';
import classNames from 'classnames';
import {
     ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning';

声明CollapsePanelProps接口

//是否可折叠
export type CollapsibleType = 'header' | 'disabled';export interface CollapsePanelProps {
    key: string | number;header: React.ReactNode;/** @deprecated Use `collapsible="disabled"` instead */disabled?: boolean;className?: string;style?: React.CSSProperties;showArrow?: boolean;prefixCls?: string;forceRender?: boolean;id?: string;extra?: React.ReactNode;collapsible?: CollapsibleType;
}

collapsible:是否可折叠或指定可折叠触发区域,类型为header | disabled
extra:自定义渲染每个面板右上角的内容,类型为ReactNode
forceRender:被隐藏时是否渲染 DOM 结构,类型为boolean
header:面板头内容,类型为ReactNode
key:对应 activeKey,类型为string | number
showArrow:是否展示当前面板上的箭头,类型为boolean

实现类

const CollapsePanel: React.FC<CollapsePanelProps> = props => {
    devWarning(!('disabled' in props),'Collapse.Panel','`disabled` is deprecated. Please use `collapsible="disabled"` instead.',);const {
     getPrefixCls } = React.useContext(ConfigContext);const {
     prefixCls: customizePrefixCls, className = '', showArrow = true } = props;const prefixCls = getPrefixCls('collapse', customizePrefixCls);const collapsePanelClassName = classNames({
    [`${
      prefixCls}-no-arrow`]: !showArrow,},className,);return <RcCollapse.Panel {
    ...props} prefixCls={
    prefixCls} className={
    collapsePanelClassName} />;
};
  相关解决方案