fix: tabs

pull/2494/head
tanjinzhou 2020-06-24 16:07:03 +08:00
parent 8ce8e9a821
commit 60cd5475c1
15 changed files with 53 additions and 40 deletions

@ -1 +1 @@
Subproject commit 7e7899bc49e5e5ebe4716a5ba12215ecfe0d3d22 Subproject commit 19713260a1fcd951d75129e542f40c8e7c1bac35

View File

@ -63,3 +63,9 @@ v-model -> v-model:value
## Switch ## Switch
v-model -> v-model:checked v-model -> v-model:checked
## tabs
v-model -> v-model:activeKey
renderTabBar({props, on, style, class}, DefaultTabBar) -> {DefaultTabBar, ...props} 多参数改成单参数并且扁平化处理

View File

@ -141,7 +141,7 @@ const getComponent = (instance, prop, options = instance, execute = true) => {
const temp = instance.props && instance.props[prop]; const temp = instance.props && instance.props[prop];
if (temp !== undefined) { if (temp !== undefined) {
return typeof temp === 'function' && execute ? temp(options) : temp; return typeof temp === 'function' && execute ? temp(options) : temp;
} else if (instance.children && instance.children[name]) { } else if (instance.children && instance.children[prop]) {
let com = instance.children[prop]; let com = instance.children[prop];
com = execute && com ? com(options) : com; com = execute && com ? com(options) : com;
return Array.isArray(com) && com.length === 1 ? com[0] : com; return Array.isArray(com) && com.length === 1 ? com[0] : com;

View File

@ -3,7 +3,6 @@ import DownOutlined from '@ant-design/icons-vue/DownOutlined';
import LeftOutlined from '@ant-design/icons-vue/LeftOutlined'; import LeftOutlined from '@ant-design/icons-vue/LeftOutlined';
import RightOutlined from '@ant-design/icons-vue/RightOutlined'; 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 PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
const TabBar = { const TabBar = {
@ -74,12 +73,8 @@ const TabBar = {
class: cls, class: cls,
}; };
let RenderTabBar;
if (renderTabBar) { if (renderTabBar) {
RenderTabBar = renderTabBar(renderProps, ScrollableInkTabBar); return renderTabBar({ ...renderProps, DefaultTabBar: ScrollableInkTabBar });
// https://github.com/vueComponent/ant-design-vue/issues/2157
return cloneElement(RenderTabBar, renderProps);
} else { } else {
return <ScrollableInkTabBar {...renderProps} />; return <ScrollableInkTabBar {...renderProps} />;
} }

View File

@ -21,10 +21,7 @@ import TabBar from './TabBar';
export default { export default {
TabPane, TabPane,
name: 'ATabs', name: 'ATabs',
model: { inheritAttrs: false,
prop: 'activeKey',
event: 'change',
},
props: { props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
@ -88,8 +85,8 @@ export default {
hideAdd, hideAdd,
renderTabBar, renderTabBar,
} = props; } = props;
const { class: className, style, ...restProps } = this.$attrs; const { class: className, ...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(getSlot(this)); const children = filterEmpty(getSlot(this));
@ -151,7 +148,7 @@ export default {
const renderTabBarSlot = renderTabBar || this.$slots.renderTabBar; const renderTabBarSlot = renderTabBar || this.$slots.renderTabBar;
const tabBarProps = { const tabBarProps = {
...this.$props, ...props,
prefixCls, prefixCls,
tabBarExtraContent, tabBarExtraContent,
renderTabBar: renderTabBarSlot, renderTabBar: renderTabBarSlot,
@ -162,7 +159,7 @@ export default {
[`${prefixCls}-card-content`]: type.indexOf('card') >= 0, [`${prefixCls}-card-content`]: type.indexOf('card') >= 0,
}; };
const tabsProps = { const tabsProps = {
...getOptionProps(this), ...props,
prefixCls, prefixCls,
tabBarPosition: tabPosition, tabBarPosition: tabPosition,
// https://github.com/vueComponent/ant-design-vue/issues/2030 // https://github.com/vueComponent/ant-design-vue/issues/2030

View File

@ -84,6 +84,7 @@ function componentDidUpdate(component, init) {
export default { export default {
name: 'InkTabBarNode', name: 'InkTabBarNode',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false,
props: { props: {
inkBarAnimated: { inkBarAnimated: {
type: Boolean, type: Boolean,
@ -99,13 +100,13 @@ export default {
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
}, },
updated() { updated() {
this.$nextTick(function() { this.$nextTick(() => {
componentDidUpdate(this); componentDidUpdate(this);
}); });
}, },
mounted() { mounted() {
this.$nextTick(function() { this.$nextTick(() => {
componentDidUpdate(this, true); componentDidUpdate(this, true);
}); });
}, },

View File

@ -7,18 +7,6 @@ import SaveRef from './SaveRef';
export default { export default {
name: 'ScrollableInkTabBar', name: 'ScrollableInkTabBar',
inheritAttrs: false, inheritAttrs: false,
props: [
'extraContent',
'inkBarAnimated',
'tabBarGutter',
'prefixCls',
'navWrapper',
'tabBarPosition',
'panels',
'activeKey',
'prevIcon',
'nextIcon',
],
render() { render() {
const { default: renderTabBarNode } = this.$slots; const { default: renderTabBarNode } = this.$slots;
return ( return (

View File

@ -10,6 +10,7 @@ function noop() {}
export default { export default {
name: 'ScrollableTabBarNode', name: 'ScrollableTabBarNode',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false,
props: { props: {
activeKey: PropTypes.any, activeKey: PropTypes.any,
getRef: PropTypes.func.def(() => {}), getRef: PropTypes.func.def(() => {}),

View File

@ -3,17 +3,18 @@ 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'; import { getSlot } from '../../_util/props-util';
import { getDataAttr } from './utils';
function noop() {} function noop() {}
export default { export default {
name: 'TabBarRootNode', name: 'TabBarRootNode',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false,
props: { props: {
saveRef: PropTypes.func.def(noop), saveRef: PropTypes.func.def(noop),
getRef: PropTypes.func.def(noop), getRef: PropTypes.func.def(noop),
prefixCls: PropTypes.string.def(''), prefixCls: PropTypes.string.def(''),
tabBarPosition: PropTypes.string.def('top'), tabBarPosition: PropTypes.string.def('top'),
extraContent: PropTypes.any, extraContent: PropTypes.any,
onKeydown: PropTypes.func,
}, },
methods: { methods: {
onKeyDown(e) { onKeyDown(e) {
@ -22,8 +23,10 @@ export default {
}, },
render() { render() {
const { prefixCls, onKeyDown, tabBarPosition, extraContent } = this; const { prefixCls, onKeyDown, tabBarPosition, extraContent } = this;
const { class: className, style, onKeydown, ...restProps } = this.$attrs;
const cls = { const cls = {
[`${prefixCls}-bar`]: true, [`${prefixCls}-bar`]: true,
[className]: !!className,
}; };
const topOrBottom = tabBarPosition === 'top' || tabBarPosition === 'bottom'; const topOrBottom = tabBarPosition === 'top' || tabBarPosition === 'bottom';
const tabBarExtraContentStyle = topOrBottom ? { float: 'right' } : {}; const tabBarExtraContentStyle = topOrBottom ? { float: 'right' } : {};
@ -48,7 +51,9 @@ export default {
class={cls} class={cls}
tabIndex="0" tabIndex="0"
onKeydown={onKeyDown} onKeydown={onKeyDown}
style={style}
{...createRefHooks(this.saveRef('root'))} {...createRefHooks(this.saveRef('root'))}
{...getDataAttr(restProps)}
> >
{newChildren} {newChildren}
</div> </div>

View File

@ -8,6 +8,7 @@ function noop() {}
export default { export default {
name: 'TabBarTabsNode', name: 'TabBarTabsNode',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false,
props: { props: {
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
panels: PropTypes.any.def([]), panels: PropTypes.any.def([]),

View File

@ -6,7 +6,6 @@ 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: {
@ -17,6 +16,7 @@ export default {
tabBarPosition: PropTypes.string, tabBarPosition: PropTypes.string,
direction: PropTypes.string, direction: PropTypes.string,
destroyInactiveTabPane: PropTypes.bool, destroyInactiveTabPane: PropTypes.bool,
children: PropTypes.any,
}, },
computed: { computed: {
classes() { classes() {
@ -52,9 +52,16 @@ export default {
}, },
}, },
render() { render() {
const { activeKey, tabBarPosition, animated, animatedWithMargin, direction, classes } = this; const {
activeKey,
tabBarPosition,
animated,
animatedWithMargin,
direction,
classes,
children,
} = this;
let style = {}; let style = {};
const children = getSlot(this);
if (animated && children) { if (animated && children) {
const activeIndex = getActiveIndex(children, activeKey); const activeIndex = getActiveIndex(children, activeKey);
if (activeIndex !== -1) { if (activeIndex !== -1) {

View File

@ -7,6 +7,7 @@ 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';
import { getDataAttr } from './utils';
function getDefaultActiveKey(props) { function getDefaultActiveKey(props) {
let activeKey; let activeKey;
@ -54,6 +55,10 @@ export default {
} else { } else {
activeKey = getDefaultActiveKey(props); activeKey = getDefaultActiveKey(props);
} }
this.panelSentinelStart = undefined;
this.panelSentinelEnd = undefined;
this.sentinelStart = undefined;
this.sentinelEnd = undefined;
return { return {
_activeKey: activeKey, _activeKey: activeKey,
}; };
@ -187,7 +192,7 @@ export default {
direction, direction,
tabBarGutter, tabBarGutter,
} = props; } = props;
const { class: className, onChange, ...restProps } = this.$attrs; const { class: className, onChange, style, ...restProps } = this.$attrs;
const cls = { const cls = {
[className]: className, [className]: className,
[prefixCls]: 1, [prefixCls]: 1,
@ -242,7 +247,8 @@ export default {
contents.push(tabBar, sentinelStart, tabContent, sentinelEnd); contents.push(tabBar, sentinelStart, tabContent, sentinelEnd);
} }
const p = { const p = {
...restProps, ...getDataAttr(restProps),
style,
onScroll: this.onScroll, onScroll: this.onScroll,
class: cls, class: cls,
}; };

View File

@ -1,7 +1,8 @@
import { isVNode } from 'vue';
export function toArray(children) { export function toArray(children) {
const c = []; const c = [];
children.forEach(child => { children.forEach(child => {
if (child.data) { if (isVNode(child)) {
c.push(child); c.push(child);
} }
}); });
@ -100,6 +101,9 @@ function getTypeValue(start, current, end, tabNode, wrapperNode) {
const { childNodes } = tabNode.parentNode; const { childNodes } = tabNode.parentNode;
Array.prototype.some.call(childNodes, node => { Array.prototype.some.call(childNodes, node => {
if (!node.tagName) {
return false;
}
const style = window.getComputedStyle(node); const style = window.getComputedStyle(node);
if (node !== tabNode) { if (node !== tabNode) {
total += toNum(style, `margin-${start}`); total += toNum(style, `margin-${start}`);

View File

@ -2,7 +2,7 @@ import '@babel/polyfill';
import { createApp } from 'vue'; import { createApp } from 'vue';
import App from './App.vue'; import App from './App.vue';
import Avatar from 'ant-design-vue/avatar'; import Avatar from 'ant-design-vue/avatar';
// import Breadcrumb from 'ant-design-vue/breadcrumb'; import Breadcrumb from 'ant-design-vue/breadcrumb';
import Button from 'ant-design-vue/button'; import Button from 'ant-design-vue/button';
import Comment from 'ant-design-vue/comment'; import Comment from 'ant-design-vue/comment';
import Drawer from 'ant-design-vue/drawer'; import Drawer from 'ant-design-vue/drawer';
@ -37,6 +37,7 @@ import Dropdown from 'ant-design-vue/dropdown';
import Steps from 'ant-design-vue/steps'; import Steps from 'ant-design-vue/steps';
import Switch from 'ant-design-vue/switch'; import Switch from 'ant-design-vue/switch';
import Layout from 'ant-design-vue/layout'; import Layout from 'ant-design-vue/layout';
import Tabs from 'ant-design-vue/tabs';
import 'ant-design-vue/style.js'; import 'ant-design-vue/style.js';
const basic = { const basic = {
@ -54,7 +55,7 @@ app
.component('CN', { ...basic }) .component('CN', { ...basic })
.component('US', { ...basic }) .component('US', { ...basic })
.use(Avatar) .use(Avatar)
// .use(Breadcrumb) .use(Breadcrumb)
.use(Button) .use(Button)
.use(Comment) .use(Comment)
.use(ConfigProvider) .use(ConfigProvider)
@ -87,4 +88,5 @@ app
.use(Steps) .use(Steps)
.use(Switch) .use(Switch)
.use(Layout) .use(Layout)
.use(Tabs)
.mount('#app'); .mount('#app');

View File

@ -160,7 +160,7 @@
"vue-i18n": "^8.3.2", "vue-i18n": "^8.3.2",
"vue-infinite-scroll": "^2.0.2", "vue-infinite-scroll": "^2.0.2",
"vue-jest": "^3.0.5", "vue-jest": "^3.0.5",
"vue-loader": "^16.0.0-beta.2", "vue-loader": "^16.0.0-beta.4",
"vue-router": "^4.0.0-alpha.12", "vue-router": "^4.0.0-alpha.12",
"vue-server-renderer": "^2.6.11", "vue-server-renderer": "^2.6.11",
"vue-virtual-scroller": "^1.0.0", "vue-virtual-scroller": "^1.0.0",