官方文档 https://ant.design/components/collapse-cn/

目录

一、antd中的collapse

  代码目录

  1、组件结构图(♦♦♦重要)

  2、源码节选:antd/components/collapse/collapse.tsx

  3、源码节选:antd/components/collapse/CollapsePanel.tsx

二、RcCollapse

  代码目录

  1、组件内部属性结构及方法调用关系图(♦♦♦重要

  2、组件应用的设计模式(♦♦♦重要

  3、源码节选:rc-collapse/Collapse.jsx

  4、源码节选:rc-collapse/panel.jsx

  

一、antd中的collapse

antd组件中有些使用了React 底层基础组件(查看具体列表点这里),collapse就是这种类型的组件

antd中collapse主要源码及组成结构如下,其中红色标注的Rc开头的组件是React底层基础组件

代码目录

1、组件结构图:

2、antd/components/collapse/collapse.tsx

export default class Collapse extends React.Component<CollapseProps, any> {
static Panel = CollapsePanel; static defaultProps = {
prefixCls: 'ant-collapse',
bordered: true,
openAnimation: { ...animation, appear() { } },
}; renderExpandIcon = () => {
return (
<Icon type="right" className={`arrow`} />
);
} render() {
const { prefixCls, className = '', bordered } = this.props;
const collapseClassName = classNames({
[`${prefixCls}-borderless`]: !bordered,
}, className);
return (
<RcCollapse
{...this.props}
className={collapseClassName}
expandIcon={this.renderExpandIcon}
/>
);
}
}

3、antd/components/collapse/CollapsePanel.tsx

export default class CollapsePanel extends React.Component<CollapsePanelProps, {}> {
render() {
const { prefixCls, className = '', showArrow = true } = this.props;
const collapsePanelClassName = classNames({
[`${prefixCls}-no-arrow`]: !showArrow,
}, className);
return <RcCollapse.Panel {...this.props} className={collapsePanelClassName} />;
}
}

二、RcCollapse

由上述Collapse源码不难看出,折叠面板组件的实现逻辑主要在RcCollapse中,下面是核心代码、组件内部属性结构及方法调用关系图

代码目录

1、组件内部属性结构及方法调用关系图

2、组件应用的设计模式

这个组件中主要使用里“聪明组件和傻瓜组件”模式、“组合组件”模式

a、聪明组件和傻瓜组件:

  遵循职责分离原则,把获取和管理数据的逻辑放在父组件,作为聪明组件;把渲染界面的逻辑放在子组件,也就是傻瓜组件

  聪明组件:Collapse,负责获取和管理数据

    • getItems(),获取数据,将props中的数据传递给子组件CollapsePanel;
    • onClickItem(),管理数据,计算active的值传递给子组件;

  傻瓜组件:Panel,只负责渲染;

    • 根据父组件传入的数据控制渲染逻辑,如active时的渲染效果

b、组合组件:

  适用场景:Collapse组件中Collapse是一个容器,包含一个或多个CollapsePanel,可以有一个(手风琴)或多个Panel展开(active),展开的样式不同与未展开

  一般实现:每个Panel中传入isActive状态和onclick方法,在Panel内部实现渲染逻辑

  缺陷:每个Panel中要写多个props参数

       每个Panel中处理onclick的相同逻辑,重复代码,增加Panel成本高

       Collapse中控制active逻辑在每次新增Panel时也要修改

  组合组件模式:借助React.Children.map或React.cloneElement使列表中多个子组件的公共处理移到父组件中统一处理

  Collapse中的实现:Collapse渲染时调用this.getItems(),在this.getItems()中使用React.Children.map配置panel的onItemClick事件和activeKey等其他属性

             Panel只在点击事件时调用父组件中定义的onItemClick,没有冗余代码,降低了增加Panel的成本

PS:组件设计模式详细内容可以自行查找相关资料,推荐掘金小册《React 实战:设计模式和最佳实践》,本文部分内容摘自该文

3、rc-collapse/Collapse.jsx

class Collapse extends Component {
constructor(props) {
super(props);
……this.state = {
……
};
} componentWillReceiveProps(nextProps) {
……
} onClickItem(key) {
……
} getItems() {
const activeKey = this.state.activeKey;
const { prefixCls, accordion, destroyInactivePanel, expandIcon } = this.props;
const newChildren = []; Children.forEach(this.props.children, (child, index) => {
if (!child) return;
// If there is no key provide, use the panel order as default key
const key = child.key || String(index);
const { header, headerClass, disabled } = child.props;
let isActive = false;
if (accordion) {
isActive = activeKey[0] === key;
} else {
isActive = activeKey.indexOf(key) > -1;
} const props = {
……
openAnimation: this.state.openAnimation,
accordion,
children: child.props.children,
onItemClick: disabled ? null : () => this.onClickItem(key),
expandIcon,
}; newChildren.push(React.cloneElement(child, props));
}); return newChildren;
} setActiveKey(activeKey) {
if (!('activeKey' in this.props)) {
this.setState({ activeKey });
}
this.props.onChange(this.props.accordion ? activeKey[0] : activeKey);
} render() {
const { prefixCls, className, style, accordion } = this.props;
const collapseClassName = classNames({
[prefixCls]: true,
[className]: !!className,
});
return (
<div className={collapseClassName} style={style} role={accordion ? 'tablist' : null}>
{this.getItems()}
</div>
);
}
}

4、rc-collapse/panel.jsx

class CollapsePanel extends Component {
handleItemClick = () => {
if (this.props.onItemClick) {
this.props.onItemClick();
}
} handleKeyPress = (e) => {
if (e.key === 'Enter' || e.keyCode === 13 || e.which === 13) {
this.handleItemClick();
}
} render() {
const {
……
} = this.props;
const headerCls = classNames(`${prefixCls}-header`, {
[headerClass]: headerClass,
});
const itemCls = classNames({
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-active`]: isActive,
[`${prefixCls}-item-disabled`]: disabled,
}, className); let icon = null;
if (showArrow && typeof expandIcon === 'function') {
icon = React.createElement(expandIcon, { ...this.props });
}
return (
<div className={itemCls} style={style} id={id}>
<div
className={headerCls}
onClick={this.handleItemClick}
role={accordion ? 'tab' : 'button'}
tabIndex={disabled ? -1 : 0}
aria-expanded={`${isActive}`}
onKeyPress={this.handleKeyPress}
>
{showArrow && (icon || <i className="arrow" />)}
{header}
</div>
<Animate
showProp="isActive"
exclusive
component=""
animation={this.props.openAnimation}
>
<PanelContent
prefixCls={prefixCls}
isActive={isActive}
destroyInactivePanel={destroyInactivePanel}
forceRender={forceRender}
role={accordion ? 'tabpanel' : null}
>
{children}
</PanelContent>
</Animate>
</div>
);
}
}

antd源码分析之——折叠面板(collapse)的更多相关文章

  1. Bootstrap源码分析之nav、collapse

    导航分析(nav): 源码文件:_navs.scss:导航模块Mixins/_nav-divider.scss:分隔线Mixins/_nav-vertical-align.scss:垂直对齐 1.只是 ...

  2. antd源码分析之——标签页(tabs 2.Tabs关键组件功能实现)

    由于ant Tabs组件结构较复杂,共分三部分叙述,本文为目录中第二部分(高亮) 目录 一.组件结构 antd代码结构 rc-ant代码结构 1.组件树状结构 2.Context使用说明 3.rc-t ...

  3. antd源码分析之——栅格(Grid)

    官方文档 https://ant.design/components/grid-cn/ 目录 一.antd中的Grid 代码目录 1.整体思路 2.less文件结构图(♦♦♦重要) 3.less实现逻 ...

  4. antd源码分析之——对话框(modal)

    目录 一.组件结构 1.antd代码结构 2.rc-ant代码结构 3.组件结构 二.antd组件调用关系及功能详解 1.Model.tsx 2.confirm 三.rc-dialog详解 1.e.t ...

  5. antd源码分析之——标签页(tabs 3.Tabs的滚动效果)

    由于ant Tabs组件结构较复杂,共分三部分叙述,本文为目录中第三部分(高亮) 目录 一.组件结构 antd代码结构 rc-ant代码结构 1.组件树状结构 2.Context使用说明 3.rc-t ...

  6. antd源码分析之——标签页(tabs 1.组件结构)

    由于ant Tabs组件结构较复杂,共分三部分叙述,本文为目录中第一部分(高亮) 目录 一.组件结构 antd代码结构 rc-ant代码结构 1.组件树状结构 2.Context使用说明 3.rc-t ...

  7. ANTD mobile源码分析 -- popover

    最近的开发中要用到很多的各式各样的组件.但是发现ant design mobile(后面简称ANTDM)里很多的资源.于是就分析一下,学习学习. ANTDM直接使用了typescript,没有用ES2 ...

  8. element-ui 组件源码分析整理笔记目录

    element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...

  9. cocos2dx骨骼动画Armature源码分析(一)

    源码分析一body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-to ...

随机推荐

  1. echarts 内存泄漏

    最近使用vue + Echarts 实现vue项目的数据可视化功能的时候,在ios环境下,点击列表页进入详情页几次就白屏了. 感觉白屏的原因是:echarts频繁初始化画图时候有内存泄漏,吃掉了所有内 ...

  2. JS-上下文练习

    /** * 因为JS没有块级作用域,if里面的foo又是以var形式声明的,所以会被提升上去, * 被赋值为undefined,之后undefined代表false,所以会进入if语句块, * foo ...

  3. ESP8266 AT指令

    无线网络名称 ESP_XXXXXX,后面的数字是MAC地址后几位 应用模式: AT+CWMODE? //查询 AT+CWMODE=<mode> //设置(重启后生效).1-Station模 ...

  4. B站视频下载

    借助Chrome插件 bilibili哔哩哔哩下载助手 在谷歌应用商城下载安装后在在浏览器右上角显示如下图标 打开想要下载的视频,网页右下角会有如下图标,点击该图标 点击下面的合并下载按钮即可 htt ...

  5. ssh: Bad configuration option: usedns

    某天突然听到同事说服务器上git用不了了,上去一看,确实用不了了,git pull报出了如下错误: $ git pull /etc/: Bad configuration option: usedns ...

  6. beego学习笔记一:创建第一个beego Web项目 转

    前提工作 环境搭建,可以参考如下两篇教程:搭建Go语言环境1搭建Go语言环境2 安装beego beego 的安装是典型的 Go 安装包的形式: go get github.com/astaxie/b ...

  7. windows 10 mysql-8.0.17-winx64的安装

    1.官网下载,并解压 https://dev.mysql.com/downloads/mysql/ 下载下来之后是一个zip的压缩包文件:mysql-5.7.26-winx64.zip,然后对这个文件 ...

  8. Vue介绍:vue项目搭建

    一.环境搭建 二.项目创建 三.认识项目 四.项目功能 一.环境搭建 *安装node 官网下载安装包,傻瓜式安装:https://nodejs.org/zh-cn/ *安装cnpm npm insta ...

  9. u-boot移植易用性设置

    u-boot移植易用性设置 以下设置使用的u-boot版本为u-boot-2012.04.01 环境参数 在Flash上划分了一块区域用于存储环境变量,所以当u-boot启动时会有如下操作: 读取Fl ...

  10. kotlin字符串比较&空值处理&when表达式

    字符串比较: 字符串的比较也是实际中比较常见的,下面来看下它的比较跟java中有啥不同,下面走起! 如我们所预期,其结果: 下面再来: 如果是java,结果肯定是为false,因为"==&q ...