feat: update tabs
parent
132a1e58bf
commit
8ce8e9a821
|
@ -1,12 +1,12 @@
|
||||||
import { inject } from 'vue';
|
import { inject } from 'vue';
|
||||||
import omit from 'omit.js';
|
|
||||||
import Tabs from '../tabs';
|
import Tabs from '../tabs';
|
||||||
import Row from '../row';
|
import Row from '../row';
|
||||||
import Col from '../col';
|
import Col from '../col';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import { getComponent, getSlotOptions, filterEmpty, getListeners } from '../_util/props-util';
|
import { getComponent, filterEmpty, getSlot } from '../_util/props-util';
|
||||||
import BaseMixin from '../_util/BaseMixin';
|
import BaseMixin from '../_util/BaseMixin';
|
||||||
import { ConfigConsumerProps } from '../config-provider';
|
import { ConfigConsumerProps } from '../config-provider';
|
||||||
|
import isPlainObject from 'lodash/isPlainObject';
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
export default {
|
export default {
|
||||||
|
@ -54,7 +54,7 @@ export default {
|
||||||
isContainGrid(obj = []) {
|
isContainGrid(obj = []) {
|
||||||
let containGrid;
|
let containGrid;
|
||||||
obj.forEach(element => {
|
obj.forEach(element => {
|
||||||
if (element && getSlotOptions(element).__ANT_CARD_GRID) {
|
if (element && isPlainObject(element.type) && element.type.__ANT_CARD_GRID) {
|
||||||
containGrid = true;
|
containGrid = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -75,18 +75,17 @@ export default {
|
||||||
activeTabKey,
|
activeTabKey,
|
||||||
defaultActiveTabKey,
|
defaultActiveTabKey,
|
||||||
} = this.$props;
|
} = this.$props;
|
||||||
|
const children = getSlot(this);
|
||||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||||
const prefixCls = getPrefixCls('card', customizePrefixCls);
|
const prefixCls = getPrefixCls('card', customizePrefixCls);
|
||||||
|
|
||||||
const { $slots, $scopedSlots } = this;
|
|
||||||
const tabBarExtraContent = getComponent(this, 'tabBarExtraContent');
|
const tabBarExtraContent = getComponent(this, 'tabBarExtraContent');
|
||||||
const classString = {
|
const classString = {
|
||||||
[`${prefixCls}`]: true,
|
[`${prefixCls}`]: true,
|
||||||
[`${prefixCls}-loading`]: loading,
|
[`${prefixCls}-loading`]: loading,
|
||||||
[`${prefixCls}-bordered`]: bordered,
|
[`${prefixCls}-bordered`]: bordered,
|
||||||
[`${prefixCls}-hoverable`]: !!hoverable,
|
[`${prefixCls}-hoverable`]: !!hoverable,
|
||||||
[`${prefixCls}-contain-grid`]: this.isContainGrid($slots.default),
|
[`${prefixCls}-contain-grid`]: this.isContainGrid(children),
|
||||||
[`${prefixCls}-contain-tabs`]: tabList && tabList.length,
|
[`${prefixCls}-contain-tabs`]: tabList && tabList.length,
|
||||||
[`${prefixCls}-${size}`]: size !== 'default',
|
[`${prefixCls}-${size}`]: size !== 'default',
|
||||||
[`${prefixCls}-type-${type}`]: !!type,
|
[`${prefixCls}-type-${type}`]: !!type,
|
||||||
|
@ -142,16 +141,12 @@ export default {
|
||||||
|
|
||||||
const hasActiveTabKey = activeTabKey !== undefined;
|
const hasActiveTabKey = activeTabKey !== undefined;
|
||||||
const tabsProps = {
|
const tabsProps = {
|
||||||
props: {
|
size: 'large',
|
||||||
size: 'large',
|
[hasActiveTabKey ? 'activeKey' : 'defaultActiveKey']: hasActiveTabKey
|
||||||
[hasActiveTabKey ? 'activeKey' : 'defaultActiveKey']: hasActiveTabKey
|
? activeTabKey
|
||||||
? activeTabKey
|
: defaultActiveTabKey,
|
||||||
: defaultActiveTabKey,
|
tabBarExtraContent,
|
||||||
tabBarExtraContent,
|
onChange: this.onTabChange,
|
||||||
},
|
|
||||||
on: {
|
|
||||||
change: this.onTabChange,
|
|
||||||
},
|
|
||||||
class: `${prefixCls}-head-tabs`,
|
class: `${prefixCls}-head-tabs`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -160,10 +155,9 @@ export default {
|
||||||
tabList && tabList.length ? (
|
tabList && tabList.length ? (
|
||||||
<Tabs {...tabsProps}>
|
<Tabs {...tabsProps}>
|
||||||
{tabList.map(item => {
|
{tabList.map(item => {
|
||||||
const { tab: temp, scopedSlots = {} } = item;
|
const { tab: temp, children = {} } = item;
|
||||||
const name = scopedSlots.tab;
|
const name = children.tab;
|
||||||
const tab =
|
const tab = temp !== undefined ? temp : children[name] ? children[name](item) : null;
|
||||||
temp !== undefined ? temp : $scopedSlots[name] ? $scopedSlots[name](item) : null;
|
|
||||||
return <TabPane tab={tab} key={item.key} disabled={item.disabled} />;
|
return <TabPane tab={tab} key={item.key} disabled={item.disabled} />;
|
||||||
})}
|
})}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
@ -182,7 +176,6 @@ export default {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const children = $slots.default;
|
|
||||||
const cover = getComponent(this, 'cover');
|
const cover = getComponent(this, 'cover');
|
||||||
const coverDom = cover ? <div class={`${prefixCls}-cover`}>{cover}</div> : null;
|
const coverDom = cover ? <div class={`${prefixCls}-cover`}>{cover}</div> : null;
|
||||||
const body = (
|
const body = (
|
||||||
|
@ -190,18 +183,14 @@ export default {
|
||||||
{loading ? loadingBlock : children}
|
{loading ? loadingBlock : children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const actions = filterEmpty(this.$slots.actions);
|
const actions = filterEmpty(getComponent(this, 'action'));
|
||||||
const actionDom =
|
const actionDom =
|
||||||
actions && actions.length ? (
|
actions && actions.length ? (
|
||||||
<ul class={`${prefixCls}-actions`}>{this.getAction(actions)}</ul>
|
<ul class={`${prefixCls}-actions`}>{this.getAction(actions)}</ul>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div class={classString} ref="cardContainerRef">
|
||||||
class={classString}
|
|
||||||
ref="cardContainerRef"
|
|
||||||
{...{ on: omit(getListeners(this), ['tabChange', 'tab-change']) }}
|
|
||||||
>
|
|
||||||
{head}
|
{head}
|
||||||
{coverDom}
|
{coverDom}
|
||||||
{children ? body : null}
|
{children ? body : null}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import RightOutlined from '@ant-design/icons-vue/RightOutlined';
|
||||||
import ScrollableInkTabBar from '../vc-tabs/src/ScrollableInkTabBar';
|
import ScrollableInkTabBar from '../vc-tabs/src/ScrollableInkTabBar';
|
||||||
import { cloneElement } from '../_util/vnode';
|
import { cloneElement } from '../_util/vnode';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import { getListeners } from '../_util/props-util';
|
|
||||||
const TabBar = {
|
const TabBar = {
|
||||||
name: 'TabBar',
|
name: 'TabBar',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
|
@ -55,25 +55,22 @@ const TabBar = {
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
// Additional className for style usage
|
// Additional className for style usage
|
||||||
const cls = {
|
const cls = {
|
||||||
|
[this.$attrs.class]: this.$attrs.class,
|
||||||
[`${prefixCls}-${tabPosition}-bar`]: true,
|
[`${prefixCls}-${tabPosition}-bar`]: true,
|
||||||
[`${prefixCls}-${size}-bar`]: !!size,
|
[`${prefixCls}-${size}-bar`]: !!size,
|
||||||
[`${prefixCls}-card-bar`]: type && type.indexOf('card') >= 0,
|
[`${prefixCls}-card-bar`]: type && type.indexOf('card') >= 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderProps = {
|
const renderProps = {
|
||||||
props: {
|
...this.$props,
|
||||||
...this.$props,
|
...this.$attrs,
|
||||||
...this.$attrs,
|
inkBarAnimated,
|
||||||
inkBarAnimated,
|
extraContent: tabBarExtraContent,
|
||||||
extraContent: tabBarExtraContent,
|
prevIcon,
|
||||||
prevIcon,
|
nextIcon,
|
||||||
nextIcon,
|
|
||||||
},
|
|
||||||
style: tabBarStyle,
|
style: tabBarStyle,
|
||||||
on: getListeners(this),
|
|
||||||
class: cls,
|
class: cls,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
import ref from 'vue-ref';
|
|
||||||
import Vue from 'vue';
|
|
||||||
import Tabs from './tabs';
|
import Tabs from './tabs';
|
||||||
import TabPane from '../vc-tabs/src/TabPane';
|
import TabPane from '../vc-tabs/src/TabPane';
|
||||||
import TabContent from '../vc-tabs/src/TabContent';
|
import TabContent from '../vc-tabs/src/TabContent';
|
||||||
import Base from '../base';
|
|
||||||
|
|
||||||
Tabs.TabPane = { ...TabPane, name: 'ATabPane', __ANT_TAB_PANE: true };
|
Tabs.TabPane = { ...TabPane, name: 'ATabPane', __ANT_TAB_PANE: true };
|
||||||
Tabs.TabContent = { ...TabContent, name: 'ATabContent' };
|
Tabs.TabContent = { ...TabContent, name: 'ATabContent' };
|
||||||
Vue.use(ref, { name: 'ant-ref' });
|
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
Tabs.install = function(Vue) {
|
Tabs.install = function(app) {
|
||||||
Vue.use(Base);
|
app.component(Tabs.name, Tabs);
|
||||||
Vue.component(Tabs.name, Tabs);
|
app.component(Tabs.TabPane.name, Tabs.TabPane);
|
||||||
Vue.component(Tabs.TabPane.name, Tabs.TabPane);
|
app.component(Tabs.TabContent.name, Tabs.TabContent);
|
||||||
Vue.component(Tabs.TabContent.name, Tabs.TabContent);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Tabs;
|
export default Tabs;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { inject } from 'vue';
|
||||||
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
|
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
|
||||||
import PlusOutlined from '@ant-design/icons-vue/PlusOutlined';
|
import PlusOutlined from '@ant-design/icons-vue/PlusOutlined';
|
||||||
import VcTabs, { TabPane } from '../vc-tabs/src';
|
import VcTabs, { TabPane } from '../vc-tabs/src';
|
||||||
|
@ -5,10 +6,12 @@ import TabContent from '../vc-tabs/src/TabContent';
|
||||||
import { isFlexSupported } from '../_util/styleChecker';
|
import { isFlexSupported } from '../_util/styleChecker';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import {
|
import {
|
||||||
getComponentFromProp,
|
getComponent,
|
||||||
getOptionProps,
|
getOptionProps,
|
||||||
filterEmpty,
|
filterEmpty,
|
||||||
getListeners,
|
findDOMNode,
|
||||||
|
getPropsData,
|
||||||
|
getSlot,
|
||||||
} from '../_util/props-util';
|
} from '../_util/props-util';
|
||||||
import { cloneElement } from '../_util/vnode';
|
import { cloneElement } from '../_util/vnode';
|
||||||
import isValid from '../_util/isValid';
|
import isValid from '../_util/isValid';
|
||||||
|
@ -37,12 +40,14 @@ export default {
|
||||||
tabBarGutter: PropTypes.number,
|
tabBarGutter: PropTypes.number,
|
||||||
renderTabBar: PropTypes.func,
|
renderTabBar: PropTypes.func,
|
||||||
},
|
},
|
||||||
inject: {
|
setup() {
|
||||||
configProvider: { default: () => ConfigConsumerProps },
|
return {
|
||||||
|
configProvider: inject('configProvider', ConfigConsumerProps),
|
||||||
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const NO_FLEX = ' no-flex';
|
const NO_FLEX = ' no-flex';
|
||||||
const tabNode = this.$el;
|
const tabNode = findDOMNode(this);
|
||||||
if (tabNode && !isFlexSupported && tabNode.className.indexOf(NO_FLEX) === -1) {
|
if (tabNode && !isFlexSupported && tabNode.className.indexOf(NO_FLEX) === -1) {
|
||||||
tabNode.className += NO_FLEX;
|
tabNode.className += NO_FLEX;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +60,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleChange(activeKey) {
|
handleChange(activeKey) {
|
||||||
|
this.$emit('update:activeKey', activeKey);
|
||||||
this.$emit('change', activeKey);
|
this.$emit('change', activeKey);
|
||||||
},
|
},
|
||||||
createNewTab(targetKey) {
|
createNewTab(targetKey) {
|
||||||
|
@ -82,11 +88,12 @@ export default {
|
||||||
hideAdd,
|
hideAdd,
|
||||||
renderTabBar,
|
renderTabBar,
|
||||||
} = props;
|
} = props;
|
||||||
|
const { class: className, style, ...restProps } = this.$attrs;
|
||||||
const getPrefixCls = this.configProvider().getPrefixCls;
|
const getPrefixCls = this.configProvider().getPrefixCls;
|
||||||
const prefixCls = getPrefixCls('tabs', customizePrefixCls);
|
const prefixCls = getPrefixCls('tabs', customizePrefixCls);
|
||||||
const children = filterEmpty(this.$slots.default);
|
const children = filterEmpty(getSlot(this));
|
||||||
|
|
||||||
let tabBarExtraContent = getComponentFromProp(this, 'tabBarExtraContent');
|
let tabBarExtraContent = getComponent(this, 'tabBarExtraContent');
|
||||||
let tabPaneAnimated = typeof animated === 'object' ? animated.tabPane : animated;
|
let tabPaneAnimated = typeof animated === 'object' ? animated.tabPane : animated;
|
||||||
|
|
||||||
// card tabs should not have animation
|
// card tabs should not have animation
|
||||||
|
@ -94,6 +101,7 @@ export default {
|
||||||
tabPaneAnimated = 'animated' in props ? tabPaneAnimated : false;
|
tabPaneAnimated = 'animated' in props ? tabPaneAnimated : false;
|
||||||
}
|
}
|
||||||
const cls = {
|
const cls = {
|
||||||
|
[className]: className,
|
||||||
[`${prefixCls}-vertical`]: tabPosition === 'left' || tabPosition === 'right',
|
[`${prefixCls}-vertical`]: tabPosition === 'left' || tabPosition === 'right',
|
||||||
[`${prefixCls}-${size}`]: !!size,
|
[`${prefixCls}-${size}`]: !!size,
|
||||||
[`${prefixCls}-card`]: type.indexOf('card') >= 0,
|
[`${prefixCls}-card`]: type.indexOf('card') >= 0,
|
||||||
|
@ -105,7 +113,7 @@ export default {
|
||||||
if (type === 'editable-card') {
|
if (type === 'editable-card') {
|
||||||
childrenWithClose = [];
|
childrenWithClose = [];
|
||||||
children.forEach((child, index) => {
|
children.forEach((child, index) => {
|
||||||
const props = getOptionProps(child);
|
const props = getPropsData(child);
|
||||||
let closable = props.closable;
|
let closable = props.closable;
|
||||||
closable = typeof closable === 'undefined' ? true : closable;
|
closable = typeof closable === 'undefined' ? true : closable;
|
||||||
const closeIcon = closable ? (
|
const closeIcon = closable ? (
|
||||||
|
@ -116,14 +124,12 @@ export default {
|
||||||
) : null;
|
) : null;
|
||||||
childrenWithClose.push(
|
childrenWithClose.push(
|
||||||
cloneElement(child, {
|
cloneElement(child, {
|
||||||
props: {
|
tab: (
|
||||||
tab: (
|
<div class={closable ? undefined : `${prefixCls}-tab-unclosable`}>
|
||||||
<div class={closable ? undefined : `${prefixCls}-tab-unclosable`}>
|
{getComponent(child, 'tab')}
|
||||||
{getComponentFromProp(child, 'tab')}
|
{closeIcon}
|
||||||
{closeIcon}
|
</div>
|
||||||
</div>
|
),
|
||||||
),
|
|
||||||
},
|
|
||||||
key: child.key || index,
|
key: child.key || index,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -143,40 +149,33 @@ export default {
|
||||||
<div class={`${prefixCls}-extra-content`}>{tabBarExtraContent}</div>
|
<div class={`${prefixCls}-extra-content`}>{tabBarExtraContent}</div>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
const renderTabBarSlot = renderTabBar || this.$scopedSlots.renderTabBar;
|
const renderTabBarSlot = renderTabBar || this.$slots.renderTabBar;
|
||||||
const listeners = getListeners(this);
|
|
||||||
const tabBarProps = {
|
const tabBarProps = {
|
||||||
props: {
|
...this.$props,
|
||||||
...this.$props,
|
prefixCls,
|
||||||
prefixCls,
|
tabBarExtraContent,
|
||||||
tabBarExtraContent,
|
renderTabBar: renderTabBarSlot,
|
||||||
renderTabBar: renderTabBarSlot,
|
...restProps,
|
||||||
},
|
|
||||||
on: listeners,
|
|
||||||
};
|
};
|
||||||
const contentCls = {
|
const contentCls = {
|
||||||
[`${prefixCls}-${tabPosition}-content`]: true,
|
[`${prefixCls}-${tabPosition}-content`]: true,
|
||||||
[`${prefixCls}-card-content`]: type.indexOf('card') >= 0,
|
[`${prefixCls}-card-content`]: type.indexOf('card') >= 0,
|
||||||
};
|
};
|
||||||
const tabsProps = {
|
const tabsProps = {
|
||||||
props: {
|
...getOptionProps(this),
|
||||||
...getOptionProps(this),
|
prefixCls,
|
||||||
prefixCls,
|
tabBarPosition: tabPosition,
|
||||||
tabBarPosition: tabPosition,
|
// https://github.com/vueComponent/ant-design-vue/issues/2030
|
||||||
// https://github.com/vueComponent/ant-design-vue/issues/2030
|
// 如仅传递 tabBarProps 会导致,第二次执行 renderTabBar 时,丢失 on 属性,
|
||||||
// 如仅传递 tabBarProps 会导致,第二次执行 renderTabBar 时,丢失 on 属性,
|
// 添加key之后,会在babel jsx 插件中做一次merge,最终TabBar接收的是一个新的对象,而不是 tabBarProps
|
||||||
// 添加key之后,会在babel jsx 插件中做一次merge,最终TabBar接收的是一个新的对象,而不是 tabBarProps
|
renderTabBar: () => <TabBar key="tabBar" {...tabBarProps} />,
|
||||||
renderTabBar: () => <TabBar key="tabBar" {...tabBarProps} />,
|
renderTabContent: () => (
|
||||||
renderTabContent: () => (
|
<TabContent class={contentCls} animated={tabPaneAnimated} animatedWithMargin />
|
||||||
<TabContent class={contentCls} animated={tabPaneAnimated} animatedWithMargin />
|
),
|
||||||
),
|
children: childrenWithClose.length > 0 ? childrenWithClose : children,
|
||||||
children: childrenWithClose.length > 0 ? childrenWithClose : children,
|
__propsSymbol__: Symbol(),
|
||||||
__propsSymbol__: Symbol(),
|
...restProps,
|
||||||
},
|
onChange: this.handleChange,
|
||||||
on: {
|
|
||||||
...listeners,
|
|
||||||
change: this.handleChange,
|
|
||||||
},
|
|
||||||
class: cls,
|
class: cls,
|
||||||
};
|
};
|
||||||
return <VcTabs {...tabsProps} />;
|
return <VcTabs {...tabsProps} />;
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { cloneElement } from '../../_util/vnode';
|
||||||
import PropTypes from '../../_util/vue-types';
|
import PropTypes from '../../_util/vue-types';
|
||||||
import BaseMixin from '../../_util/BaseMixin';
|
import BaseMixin from '../../_util/BaseMixin';
|
||||||
import createRefHooks from '../../_util/createRefHooks';
|
import createRefHooks from '../../_util/createRefHooks';
|
||||||
|
import { getSlot } from '../../_util/props-util';
|
||||||
function noop() {}
|
function noop() {}
|
||||||
export default {
|
export default {
|
||||||
name: 'TabBarRootNode',
|
name: 'TabBarRootNode',
|
||||||
|
@ -26,7 +27,7 @@ export default {
|
||||||
};
|
};
|
||||||
const topOrBottom = tabBarPosition === 'top' || tabBarPosition === 'bottom';
|
const topOrBottom = tabBarPosition === 'top' || tabBarPosition === 'bottom';
|
||||||
const tabBarExtraContentStyle = topOrBottom ? { float: 'right' } : {};
|
const tabBarExtraContentStyle = topOrBottom ? { float: 'right' } : {};
|
||||||
const children = this.$slots.default;
|
const children = getSlot(this);
|
||||||
let newChildren = children;
|
let newChildren = children;
|
||||||
if (extraContent) {
|
if (extraContent) {
|
||||||
newChildren = [
|
newChildren = [
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import warning from 'warning';
|
import warning from 'warning';
|
||||||
import PropTypes from '../../_util/vue-types';
|
import PropTypes from '../../_util/vue-types';
|
||||||
import BaseMixin from '../../_util/BaseMixin';
|
import BaseMixin from '../../_util/BaseMixin';
|
||||||
import { getOptionProps, getComponentFromProp } from '../../_util/props-util';
|
import { getComponent, getPropsData } from '../../_util/props-util';
|
||||||
import { isVertical } from './utils';
|
import { isVertical } from './utils';
|
||||||
|
import createRefHooks from '../../_util/createRefHooks';
|
||||||
function noop() {}
|
function noop() {}
|
||||||
export default {
|
export default {
|
||||||
name: 'TabBarTabsNode',
|
name: 'TabBarTabsNode',
|
||||||
|
@ -30,32 +31,25 @@ export default {
|
||||||
direction,
|
direction,
|
||||||
} = this.$props;
|
} = this.$props;
|
||||||
const rst = [];
|
const rst = [];
|
||||||
const renderTabBarNode = this.renderTabBarNode || this.$scopedSlots.renderTabBarNode;
|
const renderTabBarNode = this.renderTabBarNode || this.$slots.renderTabBarNode;
|
||||||
children.forEach((child, index) => {
|
children.forEach((child, index) => {
|
||||||
if (!child) {
|
if (!child) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const props = getOptionProps(child);
|
const props = getPropsData(child);
|
||||||
const key = child.key;
|
const key = child.key;
|
||||||
let cls = activeKey === key ? `${prefixCls}-tab-active` : '';
|
let cls = activeKey === key ? `${prefixCls}-tab-active` : '';
|
||||||
cls += ` ${prefixCls}-tab`;
|
cls += ` ${prefixCls}-tab`;
|
||||||
const events = { on: {} };
|
const events = {};
|
||||||
const disabled = props.disabled || props.disabled === '';
|
const disabled = props.disabled;
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
cls += ` ${prefixCls}-tab-disabled`;
|
cls += ` ${prefixCls}-tab-disabled`;
|
||||||
} else {
|
} else {
|
||||||
events.on.click = () => {
|
events.onClick = () => {
|
||||||
this.__emit('tabClick', key);
|
this.__emit('tabClick', key);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const directives = [];
|
const tab = getComponent(child, 'tab');
|
||||||
if (activeKey === key) {
|
|
||||||
directives.push({
|
|
||||||
name: 'ant-ref',
|
|
||||||
value: saveRef('activeTab'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const tab = getComponentFromProp(child, 'tab');
|
|
||||||
let gutter = tabBarGutter && index === children.length - 1 ? 0 : tabBarGutter;
|
let gutter = tabBarGutter && index === children.length - 1 ? 0 : tabBarGutter;
|
||||||
gutter = typeof gutter === 'number' ? `${gutter}px` : gutter;
|
gutter = typeof gutter === 'number' ? `${gutter}px` : gutter;
|
||||||
const marginProperty = direction === 'rtl' ? 'marginLeft' : 'marginRight';
|
const marginProperty = direction === 'rtl' ? 'marginLeft' : 'marginRight';
|
||||||
|
@ -72,7 +66,7 @@ export default {
|
||||||
class={cls}
|
class={cls}
|
||||||
key={key}
|
key={key}
|
||||||
style={style}
|
style={style}
|
||||||
{...{ directives }}
|
{...createRefHooks(activeKey === key ? saveRef('activeTab') : noop)}
|
||||||
>
|
>
|
||||||
{tab}
|
{tab}
|
||||||
</div>
|
</div>
|
||||||
|
@ -84,19 +78,6 @@ export default {
|
||||||
rst.push(node);
|
rst.push(node);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return <div {...createRefHooks(this.saveRef('navTabsContainer'))}>{rst}</div>;
|
||||||
<div
|
|
||||||
{...{
|
|
||||||
directives: [
|
|
||||||
{
|
|
||||||
name: 'ant-ref',
|
|
||||||
value: this.saveRef('navTabsContainer'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{rst}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,17 +6,15 @@ import {
|
||||||
getTransformPropValue,
|
getTransformPropValue,
|
||||||
getMarginStyle,
|
getMarginStyle,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
import { getSlot } from '../../_util/props-util';
|
||||||
export default {
|
export default {
|
||||||
name: 'TabContent',
|
name: 'TabContent',
|
||||||
props: {
|
props: {
|
||||||
animated: { type: Boolean, default: true },
|
animated: PropTypes.bool.def(true),
|
||||||
animatedWithMargin: { type: Boolean, default: true },
|
animatedWithMargin: PropTypes.bool.def(true),
|
||||||
prefixCls: {
|
prefixCls: PropTypes.string.def('ant-tabs'),
|
||||||
default: 'ant-tabs',
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
tabBarPosition: String,
|
tabBarPosition: PropTypes.string,
|
||||||
direction: PropTypes.string,
|
direction: PropTypes.string,
|
||||||
destroyInactiveTabPane: PropTypes.bool,
|
destroyInactiveTabPane: PropTypes.bool,
|
||||||
},
|
},
|
||||||
|
@ -30,10 +28,9 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getTabPanes() {
|
getTabPanes(children) {
|
||||||
const props = this.$props;
|
const props = this.$props;
|
||||||
const activeKey = props.activeKey;
|
const activeKey = props.activeKey;
|
||||||
const children = this.$slots.default || [];
|
|
||||||
const newChildren = [];
|
const newChildren = [];
|
||||||
|
|
||||||
children.forEach(child => {
|
children.forEach(child => {
|
||||||
|
@ -44,11 +41,9 @@ export default {
|
||||||
const active = activeKey === key;
|
const active = activeKey === key;
|
||||||
newChildren.push(
|
newChildren.push(
|
||||||
cloneElement(child, {
|
cloneElement(child, {
|
||||||
props: {
|
active,
|
||||||
active,
|
destroyInactiveTabPane: props.destroyInactiveTabPane,
|
||||||
destroyInactiveTabPane: props.destroyInactiveTabPane,
|
rootPrefixCls: props.prefixCls,
|
||||||
rootPrefixCls: props.prefixCls,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -59,8 +54,9 @@ export default {
|
||||||
render() {
|
render() {
|
||||||
const { activeKey, tabBarPosition, animated, animatedWithMargin, direction, classes } = this;
|
const { activeKey, tabBarPosition, animated, animatedWithMargin, direction, classes } = this;
|
||||||
let style = {};
|
let style = {};
|
||||||
if (animated && this.$slots.default) {
|
const children = getSlot(this);
|
||||||
const activeIndex = getActiveIndex(this.$slots.default, activeKey);
|
if (animated && children) {
|
||||||
|
const activeIndex = getActiveIndex(children, activeKey);
|
||||||
if (activeIndex !== -1) {
|
if (activeIndex !== -1) {
|
||||||
const animatedStyle = animatedWithMargin
|
const animatedStyle = animatedWithMargin
|
||||||
? getMarginStyle(activeIndex, tabBarPosition)
|
? getMarginStyle(activeIndex, tabBarPosition)
|
||||||
|
@ -74,7 +70,7 @@ export default {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div class={classes} style={style}>
|
<div class={classes} style={style}>
|
||||||
{this.getTabPanes()}
|
{this.getTabPanes(children || [])}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
import { inject } from 'vue';
|
||||||
import PropTypes from '../../_util/vue-types';
|
import PropTypes from '../../_util/vue-types';
|
||||||
import { getComponentFromProp } from '../../_util/props-util';
|
import { getComponent, getSlot } from '../../_util/props-util';
|
||||||
import Sentinel from './Sentinel';
|
import Sentinel from './Sentinel';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -14,13 +15,16 @@ export default {
|
||||||
closable: PropTypes.bool,
|
closable: PropTypes.bool,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
},
|
},
|
||||||
inject: {
|
setup() {
|
||||||
sentinelContext: { default: () => ({}) },
|
return {
|
||||||
|
_isActived: undefined,
|
||||||
|
sentinelContext: inject('sentinelContext', {}),
|
||||||
|
};
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
const { destroyInactiveTabPane, active, forceRender, rootPrefixCls } = this.$props;
|
const { destroyInactiveTabPane, active, forceRender, rootPrefixCls } = this.$props;
|
||||||
const children = this.$slots.default;
|
const children = getSlot(this);
|
||||||
const placeholder = getComponentFromProp(this, 'placeholder');
|
const placeholder = getComponent(this, 'placeholder');
|
||||||
this._isActived = this._isActived || active;
|
this._isActived = this._isActived || active;
|
||||||
const prefixCls = `${rootPrefixCls}-tabpane`;
|
const prefixCls = `${rootPrefixCls}-tabpane`;
|
||||||
const cls = {
|
const cls = {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import omit from 'omit.js';
|
import { provide } from 'vue';
|
||||||
import BaseMixin from '../../_util/BaseMixin';
|
import BaseMixin from '../../_util/BaseMixin';
|
||||||
import PropTypes from '../../_util/vue-types';
|
import PropTypes from '../../_util/vue-types';
|
||||||
import raf from 'raf';
|
import raf from 'raf';
|
||||||
import KeyCode from './KeyCode';
|
import KeyCode from './KeyCode';
|
||||||
import { getOptionProps, getListeners } from '../../_util/props-util';
|
import { getOptionProps } from '../../_util/props-util';
|
||||||
import { cloneElement } from '../../_util/vnode';
|
import { cloneElement } from '../../_util/vnode';
|
||||||
import Sentinel from './Sentinel';
|
import Sentinel from './Sentinel';
|
||||||
import isValid from '../../_util/isValid';
|
import isValid from '../../_util/isValid';
|
||||||
|
@ -28,10 +28,7 @@ function activeKeyIsValid(props, key) {
|
||||||
export default {
|
export default {
|
||||||
name: 'Tabs',
|
name: 'Tabs',
|
||||||
mixins: [BaseMixin],
|
mixins: [BaseMixin],
|
||||||
model: {
|
inheritAttrs: false,
|
||||||
prop: 'activeKey',
|
|
||||||
event: 'change',
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
destroyInactiveTabPane: PropTypes.bool,
|
destroyInactiveTabPane: PropTypes.bool,
|
||||||
renderTabBar: PropTypes.func.isRequired,
|
renderTabBar: PropTypes.func.isRequired,
|
||||||
|
@ -47,6 +44,7 @@ export default {
|
||||||
tabBarGutter: PropTypes.number,
|
tabBarGutter: PropTypes.number,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
provide('sentinelContext', this);
|
||||||
const props = getOptionProps(this);
|
const props = getOptionProps(this);
|
||||||
let activeKey;
|
let activeKey;
|
||||||
if ('activeKey' in props) {
|
if ('activeKey' in props) {
|
||||||
|
@ -60,11 +58,6 @@ export default {
|
||||||
_activeKey: activeKey,
|
_activeKey: activeKey,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
provide() {
|
|
||||||
return {
|
|
||||||
sentinelContext: this,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
watch: {
|
||||||
__propsSymbol__() {
|
__propsSymbol__() {
|
||||||
const nextProps = getOptionProps(this);
|
const nextProps = getOptionProps(this);
|
||||||
|
@ -86,12 +79,8 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onTabClick(activeKey, e) {
|
onTabClick(activeKey, e) {
|
||||||
if (
|
if (this.tabBar.props && this.tabBar.props.onTabClick) {
|
||||||
this.tabBar.componentOptions &&
|
this.tabBar.props.onTabClick(activeKey, e);
|
||||||
this.tabBar.componentOptions.listeners &&
|
|
||||||
this.tabBar.componentOptions.listeners.tabClick
|
|
||||||
) {
|
|
||||||
this.tabBar.componentOptions.listeners.tabClick(activeKey, e);
|
|
||||||
}
|
}
|
||||||
this.setActiveKey(activeKey);
|
this.setActiveKey(activeKey);
|
||||||
},
|
},
|
||||||
|
@ -146,6 +135,7 @@ export default {
|
||||||
_activeKey: activeKey,
|
_activeKey: activeKey,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this.$emit('update:activeKey', activeKey);
|
||||||
this.__emit('change', activeKey);
|
this.__emit('change', activeKey);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -197,7 +187,9 @@ export default {
|
||||||
direction,
|
direction,
|
||||||
tabBarGutter,
|
tabBarGutter,
|
||||||
} = props;
|
} = props;
|
||||||
|
const { class: className, onChange, ...restProps } = this.$attrs;
|
||||||
const cls = {
|
const cls = {
|
||||||
|
[className]: className,
|
||||||
[prefixCls]: 1,
|
[prefixCls]: 1,
|
||||||
[`${prefixCls}-${tabBarPosition}`]: 1,
|
[`${prefixCls}-${tabBarPosition}`]: 1,
|
||||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||||
|
@ -205,32 +197,24 @@ export default {
|
||||||
|
|
||||||
this.tabBar = renderTabBar();
|
this.tabBar = renderTabBar();
|
||||||
const tabBar = cloneElement(this.tabBar, {
|
const tabBar = cloneElement(this.tabBar, {
|
||||||
props: {
|
prefixCls,
|
||||||
prefixCls,
|
navWrapper,
|
||||||
navWrapper,
|
tabBarPosition,
|
||||||
tabBarPosition,
|
panels: props.children,
|
||||||
panels: props.children,
|
activeKey: this.$data._activeKey,
|
||||||
activeKey: this.$data._activeKey,
|
direction,
|
||||||
direction,
|
tabBarGutter,
|
||||||
tabBarGutter,
|
onKeydown: this.onNavKeyDown,
|
||||||
},
|
onTabClick: this.onTabClick,
|
||||||
on: {
|
|
||||||
keydown: this.onNavKeyDown,
|
|
||||||
tabClick: this.onTabClick,
|
|
||||||
},
|
|
||||||
key: 'tabBar',
|
key: 'tabBar',
|
||||||
});
|
});
|
||||||
const tabContent = cloneElement(renderTabContent(), {
|
const tabContent = cloneElement(renderTabContent(), {
|
||||||
props: {
|
prefixCls,
|
||||||
prefixCls,
|
tabBarPosition,
|
||||||
tabBarPosition,
|
activeKey: this.$data._activeKey,
|
||||||
activeKey: this.$data._activeKey,
|
destroyInactiveTabPane,
|
||||||
destroyInactiveTabPane,
|
direction,
|
||||||
direction,
|
onChange: this.setActiveKey,
|
||||||
},
|
|
||||||
on: {
|
|
||||||
change: this.setActiveKey,
|
|
||||||
},
|
|
||||||
children: props.children,
|
children: props.children,
|
||||||
key: 'tabContent',
|
key: 'tabContent',
|
||||||
});
|
});
|
||||||
|
@ -257,10 +241,11 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
contents.push(tabBar, sentinelStart, tabContent, sentinelEnd);
|
contents.push(tabBar, sentinelStart, tabContent, sentinelEnd);
|
||||||
}
|
}
|
||||||
const listeners = {
|
const p = {
|
||||||
...omit(getListeners(this), ['change']),
|
...restProps,
|
||||||
scroll: this.onScroll,
|
onScroll: this.onScroll,
|
||||||
|
class: cls,
|
||||||
};
|
};
|
||||||
return <div {...{ on: listeners, class: cls }}>{contents}</div>;
|
return <div {...p}>{contents}</div>;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue