feat: update collapse (#2539)

pull/2682/head
zkwolf 2020-07-15 15:27:35 +08:00 committed by GitHub
parent 80599668df
commit 41e3630f8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 81 additions and 82 deletions

View File

@ -79,3 +79,7 @@ tabList[{scopedSlots}] -> tabList[{slots}]
## rate ## rate
v-model -> v-model:value v-model -> v-model:value
## Collapse
v-model -> v-model:activeKey

View File

@ -1,10 +1,11 @@
import { inject } from 'vue';
import animation from '../_util/openAnimation'; import animation from '../_util/openAnimation';
import { import {
getOptionProps, getOptionProps,
initDefaultProps, initDefaultProps,
getComponentFromProp, getComponent,
isValidElement, isValidElement,
getListeners, getSlot,
} from '../_util/props-util'; } from '../_util/props-util';
import { cloneElement } from '../_util/vnode'; import { cloneElement } from '../_util/vnode';
import VcCollapse, { collapseProps } from '../vc-collapse'; import VcCollapse, { collapseProps } from '../vc-collapse';
@ -13,21 +14,19 @@ import { ConfigConsumerProps } from '../config-provider';
export default { export default {
name: 'ACollapse', name: 'ACollapse',
model: {
prop: 'activeKey',
event: 'change',
},
props: initDefaultProps(collapseProps(), { props: initDefaultProps(collapseProps(), {
bordered: true, bordered: true,
openAnimation: animation, openAnimation: animation,
expandIconPosition: 'left', expandIconPosition: 'left',
}), }),
inject: { setup() {
configProvider: { default: () => ConfigConsumerProps }, return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
}, },
methods: { methods: {
renderExpandIcon(panelProps, prefixCls) { renderExpandIcon(panelProps, prefixCls) {
const expandIcon = getComponentFromProp(this, 'expandIcon', panelProps); const expandIcon = getComponent(this, 'expandIcon', panelProps);
const icon = expandIcon || <RightOutlined rotate={panelProps.isActive ? 90 : undefined} />; const icon = expandIcon || <RightOutlined rotate={panelProps.isActive ? 90 : undefined} />;
return isValidElement(Array.isArray(expandIcon) ? icon[0] : icon) return isValidElement(Array.isArray(expandIcon) ? icon[0] : icon)
? cloneElement(icon, { ? cloneElement(icon, {
@ -46,14 +45,12 @@ export default {
[`${prefixCls}-icon-position-${expandIconPosition}`]: true, [`${prefixCls}-icon-position-${expandIconPosition}`]: true,
}; };
const rcCollapeProps = { const rcCollapeProps = {
props: { ...getOptionProps(this),
...getOptionProps(this), prefixCls,
prefixCls, expandIcon: panelProps => this.renderExpandIcon(panelProps, prefixCls),
expandIcon: panelProps => this.renderExpandIcon(panelProps, prefixCls),
},
class: collapseClassName, class: collapseClassName,
on: getListeners(this),
}; };
return <VcCollapse {...rcCollapeProps}>{this.$slots.default}</VcCollapse>;
return <VcCollapse {...rcCollapeProps}>{getSlot(this)}</VcCollapse>;
}, },
}; };

View File

@ -1,4 +1,5 @@
import { getOptionProps, getComponentFromProp, getListeners } from '../_util/props-util'; import { inject } from 'vue';
import { getOptionProps, getComponent, getSlot } from '../_util/props-util';
import VcCollapse, { panelProps } from '../vc-collapse'; import VcCollapse, { panelProps } from '../vc-collapse';
import { ConfigConsumerProps } from '../config-provider'; import { ConfigConsumerProps } from '../config-provider';
@ -7,8 +8,10 @@ export default {
props: { props: {
...panelProps(), ...panelProps(),
}, },
inject: { setup() {
configProvider: { default: () => ConfigConsumerProps }, return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
}, },
render() { render() {
const { prefixCls: customizePrefixCls, showArrow = true } = this; const { prefixCls: customizePrefixCls, showArrow = true } = this;
@ -18,21 +21,14 @@ export default {
const collapsePanelClassName = { const collapsePanelClassName = {
[`${prefixCls}-no-arrow`]: !showArrow, [`${prefixCls}-no-arrow`]: !showArrow,
}; };
const rcCollapePanelProps = { const rcCollapePanelProps = {
props: { ...getOptionProps(this),
...getOptionProps(this), header: getComponent(this, 'header'),
prefixCls, prefixCls,
extra: getComponentFromProp(this, 'extra'), extra: getComponent(this, 'extra'),
},
class: collapsePanelClassName, class: collapsePanelClassName,
on: getListeners(this),
}; };
const header = getComponentFromProp(this, 'header'); return <VcCollapse.Panel {...rcCollapePanelProps}>{getSlot(this)}</VcCollapse.Panel>;
return (
<VcCollapse.Panel {...rcCollapePanelProps}>
{this.$slots.default}
{header ? <template slot="header">{header}</template> : null}
</VcCollapse.Panel>
);
}, },
}; };

View File

@ -2,8 +2,10 @@
exports[`Collapse should support remove expandIcon 1`] = ` exports[`Collapse should support remove expandIcon 1`] = `
<div class="ant-collapse ant-collapse-icon-position-left"> <div class="ant-collapse ant-collapse-icon-position-left">
<div role="tablist" class="ant-collapse-item"> <div class="ant-collapse-item" role="tablist">
<div role="button" tabindex="0" class="ant-collapse-header"><span role="img" aria-label="right" class="anticon anticon-right ant-collapse-arrow"><svg viewBox="64 64 896 896" focusable="false" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span>header</div> <div class="ant-collapse-header" role="button" tabindex="0" aria-expanded="false"><span class="anticon anticon-right ant-collapse-arrow" role="img" aria-label="right"><svg class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span>header
<!---->
</div>
<!----> <!---->
</div> </div>
</div> </div>

View File

@ -1,14 +1,12 @@
import Collapse from './Collapse'; import Collapse from './Collapse';
import CollapsePanel from './CollapsePanel'; import CollapsePanel from './CollapsePanel';
import Base from '../base';
Collapse.Panel = CollapsePanel; Collapse.Panel = CollapsePanel;
/* istanbul ignore next */ /* istanbul ignore next */
Collapse.install = function(Vue) { Collapse.install = function(app) {
Vue.use(Base); app.component(Collapse.name, Collapse);
Vue.component(Collapse.name, Collapse); app.component(CollapsePanel.name, CollapsePanel);
Vue.component(CollapsePanel.name, CollapsePanel);
}; };
export default Collapse; export default Collapse;

View File

@ -1,5 +1,11 @@
import BaseMixin from '../../_util/BaseMixin'; import BaseMixin from '../../_util/BaseMixin';
import { hasProp, getPropsData, isEmptyElement, initDefaultProps } from '../../_util/props-util'; import {
hasProp,
getPropsData,
isEmptyElement,
initDefaultProps,
getSlot,
} from '../../_util/props-util';
import { cloneElement } from '../../_util/vnode'; import { cloneElement } from '../../_util/vnode';
import openAnimationFactory from './openAnimationFactory'; import openAnimationFactory from './openAnimationFactory';
import { collapseProps } from './commonProps'; import { collapseProps } from './commonProps';
@ -14,10 +20,6 @@ function _toArray(activeKey) {
export default { export default {
name: 'Collapse', name: 'Collapse',
mixins: [BaseMixin], mixins: [BaseMixin],
model: {
prop: 'activeKey',
event: 'change',
},
props: initDefaultProps(collapseProps(), { props: initDefaultProps(collapseProps(), {
prefixCls: 'rc-collapse', prefixCls: 'rc-collapse',
accordion: false, accordion: false,
@ -84,32 +86,30 @@ export default {
let panelEvents = {}; let panelEvents = {};
if (!disabled && disabled !== '') { if (!disabled && disabled !== '') {
panelEvents = { panelEvents = {
itemClick: this.onClickItem, onItemClick: this.onClickItem,
}; };
} }
const props = { const props = {
key, key,
props: { panelKey: key,
panelKey: key, header,
header, headerClass,
headerClass, isActive,
isActive, prefixCls,
prefixCls, destroyInactivePanel,
destroyInactivePanel, openAnimation: this.currentOpenAnimations,
openAnimation: this.currentOpenAnimations, accordion,
accordion, expandIcon,
expandIcon, ...panelEvents,
},
on: panelEvents,
}; };
return cloneElement(child, props); return cloneElement(child, props);
}, },
getItems() { getItems() {
const newChildren = []; const newChildren = [];
this.$slots.default && getSlot(this) &&
this.$slots.default.forEach((child, index) => { getSlot(this).forEach((child, index) => {
newChildren.push(this.getNewChild(child, index)); newChildren.push(this.getNewChild(child, index));
}); });
return newChildren; return newChildren;
@ -117,6 +117,7 @@ export default {
setActiveKey(activeKey) { setActiveKey(activeKey) {
this.setState({ stateActiveKey: activeKey }); this.setState({ stateActiveKey: activeKey });
this.$emit('change', this.accordion ? activeKey[0] : activeKey); this.$emit('change', this.accordion ? activeKey[0] : activeKey);
this.$emit('update:activeKey', this.accordion ? activeKey[0] : activeKey);
}, },
}, },
render() { render() {

View File

@ -1,6 +1,7 @@
import PanelContent from './PanelContent'; import PanelContent from './PanelContent';
import { initDefaultProps, getComponentFromProp } from '../../_util/props-util'; import { initDefaultProps, getComponent, getSlot } from '../../_util/props-util';
import { panelProps } from './commonProps'; import { panelProps } from './commonProps';
import { Transition } from 'vue';
export default { export default {
name: 'Panel', name: 'Panel',
@ -35,20 +36,18 @@ export default {
expandIcon, expandIcon,
extra, extra,
} = this.$props; } = this.$props;
const { $slots } = this;
const transitionProps = { const transitionProps = {
props: Object.assign({ appear: true,
appear: true, css: false,
css: false, ...openAnimation,
}),
on: { ...openAnimation },
}; };
const headerCls = { const headerCls = {
[`${prefixCls}-header`]: true, [`${prefixCls}-header`]: true,
[headerClass]: headerClass, [headerClass]: headerClass,
}; };
const header = getComponentFromProp(this, 'header');
const header = getComponent(this, 'header');
const itemCls = { const itemCls = {
[`${prefixCls}-item`]: true, [`${prefixCls}-item`]: true,
[`${prefixCls}-item-active`]: isActive, [`${prefixCls}-item-active`]: isActive,
@ -58,11 +57,24 @@ export default {
if (showArrow && typeof expandIcon === 'function') { if (showArrow && typeof expandIcon === 'function') {
icon = expandIcon(this.$props); icon = expandIcon(this.$props);
} }
const panelContent = (
<PanelContent
vShow={isActive}
prefixCls={prefixCls}
isActive={isActive}
destroyInactivePanel={destroyInactivePanel}
forceRender={forceRender}
role={accordion ? 'tabpanel' : null}
>
{getSlot(this)}
</PanelContent>
);
return ( return (
<div class={itemCls} role="tablist"> <div class={itemCls} role="tablist">
<div <div
class={headerCls} class={headerCls}
onClick={this.handleItemClick.bind(this)} onClick={this.handleItemClick}
onKeypress={this.handleKeyPress} onKeypress={this.handleKeyPress}
role={accordion ? 'tab' : 'button'} role={accordion ? 'tab' : 'button'}
tabIndex={disabled ? -1 : 0} tabIndex={disabled ? -1 : 0}
@ -72,18 +84,7 @@ export default {
{header} {header}
{extra && <div class={`${prefixCls}-extra`}>{extra}</div>} {extra && <div class={`${prefixCls}-extra`}>{extra}</div>}
</div> </div>
<transition {...transitionProps}> <Transition {...transitionProps}>{panelContent}</Transition>
<PanelContent
v-show={isActive}
prefixCls={prefixCls}
isActive={isActive}
destroyInactivePanel={destroyInactivePanel}
forceRender={forceRender}
role={accordion ? 'tabpanel' : null}
>
{$slots.default}
</PanelContent>
</transition>
</div> </div>
); );
}, },

View File

@ -1,4 +1,5 @@
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import { getSlot } from '../../_util/props-util';
export default { export default {
name: 'PanelContent', name: 'PanelContent',
@ -20,14 +21,13 @@ export default {
return null; return null;
} }
const { prefixCls, isActive, destroyInactivePanel, forceRender, role } = this.$props; const { prefixCls, isActive, destroyInactivePanel, forceRender, role } = this.$props;
const { $slots } = this;
const contentCls = { const contentCls = {
[`${prefixCls}-content`]: true, [`${prefixCls}-content`]: true,
[`${prefixCls}-content-active`]: isActive, [`${prefixCls}-content-active`]: isActive,
}; };
const child = const child =
!forceRender && !isActive && destroyInactivePanel ? null : ( !forceRender && !isActive && destroyInactivePanel ? null : (
<div class={`${prefixCls}-content-box`}>{$slots.default}</div> <div class={`${prefixCls}-content-box`}>{getSlot(this)}</div>
); );
return ( return (
<div class={contentCls} role={role}> <div class={contentCls} role={role}>