feat: update tabs

pull/309/head
wangxueliang 2018-12-11 20:53:56 +08:00
parent 0eafff36d8
commit 2fb1de4e29
5 changed files with 154 additions and 72 deletions

View File

@ -0,0 +1,38 @@
<cn>
#### 自定义页签头
自定义页签头
</cn>
<us>
#### Customized bar of tab
Customized bar of tab.
</us>
```html
<template>
<div>
<a-tabs defaultActiveKey="1">
<a-tab-pane tab="Tab 1" key="1" style="height: 200px">Content of Tab Pane 1</a-tab-pane>
<a-tab-pane tab="Tab 2" key="2" forceRender>Content of Tab Pane 2</a-tab-pane>
<a-tab-pane tab="Tab 3" key="3">Content of Tab Pane 3</a-tab-pane>
<template slot="renderTabBar" slot-scope="props, DefaultTabBar">
<component :is="DefaultTabBar" {...props} />
</template>
</a-tabs>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods: {
callback (key) {
console.log(key)
},
},
}
</script>
```

View File

@ -10,6 +10,7 @@ import Icon from './icon'
import Position from './position' import Position from './position'
import Size from './size' import Size from './size'
import Slide from './slide' import Slide from './slide'
import CustomTabBar from './custom-tab-bar'
import CN from '../index.zh-CN.md' import CN from '../index.zh-CN.md'
import US from '../index.en-US.md' import US from '../index.en-US.md'
@ -53,16 +54,17 @@ export default {
<div> <div>
<md cn={md.cn} us={md.us}/> <md cn={md.cn} us={md.us}/>
<Basic /> <Basic />
<CardTop />
<Card />
<CustomAddTrigger />
<Disabled /> <Disabled />
<EditableCard />
<Extra />
<Icon /> <Icon />
<Position />
<Size />
<Slide/> <Slide/>
<Extra />
<Size />
<Position />
<Card />
<EditableCard />
<CardTop />
<CustomAddTrigger />
<CustomTabBar />
<api> <api>
<template slot='cn'> <template slot='cn'>
<CN/> <CN/>

View File

@ -0,0 +1,58 @@
import Icon from '../icon'
import ScrollableInkTabBar from '../vc-tabs/src/ScrollableInkTabBar'
import { cloneElement } from '../_util/vnode'
const TabBar = {
functional: true,
render (h, context) {
const {
tabBarStyle,
animated = true,
renderTabBar,
tabBarExtraContent,
tabPosition,
prefixCls,
} = context.props
const inkBarAnimated = typeof animated === 'object' ? animated.inkBar : animated
const isVertical = tabPosition === 'left' || tabPosition === 'right'
const prevIconType = isVertical ? 'up' : 'left'
const nextIconType = isVertical ? 'down' : 'right'
const prevIcon = (
<span class={`${prefixCls}-tab-prev-icon`}>
<Icon type={prevIconType} class={`${prefixCls}-tab-prev-icon-target`} />
</span>
)
const nextIcon = (
<span class={`${prefixCls}-tab-next-icon`}>
<Icon type={nextIconType} class={`${prefixCls}-tab-next-icon-target`} />
</span>
)
const renderProps = {
props: {
...context.props,
inkBarAnimated,
extraContent: tabBarExtraContent,
prevIcon,
nextIcon,
},
style: tabBarStyle,
on: {
...context.listeners,
},
}
let RenderTabBar
if (renderTabBar) {
RenderTabBar = renderTabBar(renderProps, ScrollableInkTabBar)
} else {
RenderTabBar = <ScrollableInkTabBar {...renderProps} />
}
return cloneElement(RenderTabBar, renderProps)
},
}
export default TabBar

View File

@ -1,49 +1,42 @@
import Icon from '../icon' import Icon from '../icon'
import VcTabs, { TabPane } from '../vc-tabs/src' import VcTabs, { TabPane } from '../vc-tabs/src'
import ScrollableInkTabBar from '../vc-tabs/src/ScrollableInkTabBar'
import TabContent from '../vc-tabs/src/TabContent' import TabContent from '../vc-tabs/src/TabContent'
import isFlexSupported from '../_util/isFlexSupported' import isFlexSupported from '../_util/isFlexSupported'
import { hasProp, getComponentFromProp, isEmptyElement, getSlotOptions, getOptionProps, filterEmpty, mergeProps } from '../_util/props-util' import PropTypes from '../_util/vue-types'
import warning from '../_util/warning' import { getComponentFromProp, getOptionProps, filterEmpty } from '../_util/props-util'
import { cloneElement } from '../_util/vnode' import { cloneElement } from '../_util/vnode'
import TabBar from './TabBar'
export default { export default {
TabPane, TabPane,
name: 'ATabs', name: 'ATabs',
props: { props: {
prefixCls: { type: String, default: 'ant-tabs' }, prefixCls: PropTypes.string.def('ant-tabs'),
activeKey: String, activeKey: PropTypes.string,
defaultActiveKey: String, defaultActiveKey: PropTypes.string,
hideAdd: { type: Boolean, default: false }, hideAdd: PropTypes.bool.def(false),
tabBarStyle: Object, tabBarStyle: PropTypes.object,
tabBarExtraContent: [String, Number, Function], tabBarExtraContent: PropTypes.oneOfType([
destroyInactiveTabPane: { type: Boolean, default: false }, PropTypes.string,
type: { PropTypes.number,
validator (value) { PropTypes.func,
return ['line', 'card', 'editable-card'].includes(value) ]),
}, destroyInactiveTabPane: PropTypes.bool.def(false),
}, type: PropTypes.oneOf(['line', 'card', 'editable-card']),
tabPosition: { tabPosition: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
validator (value) { size: PropTypes.oneOf(['default', 'small', 'large']),
return ['top', 'right', 'bottom', 'left'].includes(value) animated: PropTypes.oneOfType([
}, PropTypes.bool,
}, PropTypes.object,
size: { ]),
validator (value) { tabBarGutter: PropTypes.number,
return ['default', 'small', 'large'].includes(value) renderTabBar: PropTypes.func,
},
},
animated: { type: [Boolean, Object], default: undefined },
tabBarGutter: Number,
}, },
model: { model: {
prop: 'activeKey', prop: 'activeKey',
event: 'change', event: 'change',
}, },
methods: { methods: {
createNewTab (targetKey) {
this.$emit('edit', targetKey, 'add')
},
removeTab (targetKey, e) { removeTab (targetKey, e) {
e.stopPropagation() e.stopPropagation()
if (!targetKey) { if (!targetKey) {
@ -51,10 +44,12 @@ export default {
} }
this.$emit('edit', targetKey, 'remove') this.$emit('edit', targetKey, 'remove')
}, },
handleChange (activeKey) { handleChange (activeKey) {
this.$emit('change', activeKey) this.$emit('change', activeKey)
}, },
createNewTab (targetKey) {
this.$emit('edit', targetKey, 'add')
},
onTabClick (val) { onTabClick (val) {
this.$emit('tabClick', val) this.$emit('tabClick', val)
}, },
@ -74,37 +69,29 @@ export default {
} }
}, },
render (createElement) { render () {
const { const {
prefixCls, prefixCls,
size, size,
type = 'line', type = 'line',
tabPosition, tabPosition,
tabBarStyle, animated = true,
hideAdd, hideAdd,
onTabClick, renderTabBar,
onPrevClick, } = this.$props
onNextClick,
animated,
tabBarGutter,
} = this
const children = filterEmpty(this.$slots.default) const children = filterEmpty(this.$slots.default)
let tabBarExtraContent = getComponentFromProp(this, 'tabBarExtraContent') let tabBarExtraContent = getComponentFromProp(this, 'tabBarExtraContent')
let { inkBarAnimated, tabPaneAnimated } = typeof animated === 'object' ? { // eslint-disable-line let tabPaneAnimated = typeof animated === 'object' ? animated.tabPane : animated
inkBarAnimated: !!animated.inkBar, tabPaneAnimated: !!animated.tabPane,
} : {
inkBarAnimated: animated === undefined || animated, tabPaneAnimated: animated === undefined || animated,
}
// card tabs should not have animation // card tabs should not have animation
if (type !== 'line') { if (type !== 'line') {
tabPaneAnimated = animated === undefined ? false : tabPaneAnimated tabPaneAnimated = animated === undefined ? false : tabPaneAnimated
} }
const cls = { const cls = {
[`${prefixCls}-small`]: size === 'small',
[`${prefixCls}-large`]: size === 'large',
[`${prefixCls}-default`]: size === 'default',
[`${prefixCls}-vertical`]: tabPosition === 'left' || tabPosition === 'right', [`${prefixCls}-vertical`]: tabPosition === 'left' || tabPosition === 'right',
[`${prefixCls}-${size}`]: !!size,
[`${prefixCls}-card`]: type.indexOf('card') >= 0, [`${prefixCls}-card`]: type.indexOf('card') >= 0,
[`${prefixCls}-${type}`]: true, [`${prefixCls}-${type}`]: true,
[`${prefixCls}-no-animation`]: !tabPaneAnimated, [`${prefixCls}-no-animation`]: !tabPaneAnimated,
@ -120,6 +107,7 @@ export default {
const closeIcon = closable ? ( const closeIcon = closable ? (
<Icon <Icon
type='close' type='close'
class={`${prefixCls}-close-x`}
onClick={e => this.removeTab(child.key, e)} onClick={e => this.removeTab(child.key, e)}
/> />
) : null ) : null
@ -152,27 +140,23 @@ export default {
</div> </div>
) : null ) : null
const renderTabBar = () => { const renderTabBarSlot = renderTabBar || this.$scopedSlots.renderTabBar
const scrollableInkTabBarProps = { const tabBarProps = {
props: { props: {
inkBarAnimated, ...this.$props,
extraContent: tabBarExtraContent, tabBarExtraContent,
tabBarGutter, renderTabBar: renderTabBarSlot,
}, },
on: { on: {
tabClick: onTabClick, ...this.$listeners,
prevClick: onPrevClick, },
nextClick: onNextClick,
},
style: tabBarStyle,
}
return <ScrollableInkTabBar {...scrollableInkTabBarProps}/>
} }
const tabsProps = { const tabsProps = {
props: { props: {
...getOptionProps(this), ...getOptionProps(this),
tabBarPosition: tabPosition, tabBarPosition: tabPosition,
renderTabBar: renderTabBar, renderTabBar: () => <TabBar {...tabBarProps}/>,
renderTabContent: () => <TabContent animated={tabPaneAnimated} animatedWithMargin />, renderTabContent: () => <TabContent animated={tabPaneAnimated} animatedWithMargin />,
children: childrenWithClose.length > 0 ? childrenWithClose : children, children: childrenWithClose.length > 0 ? childrenWithClose : children,
__propsSymbol__: Symbol(), __propsSymbol__: Symbol(),

View File

@ -8,7 +8,7 @@ export default {
name: 'ScrollableInkTabBar', name: 'ScrollableInkTabBar',
inheritAttrs: false, inheritAttrs: false,
props: ['extraContent', 'inkBarAnimated', 'tabBarGutter', 'prefixCls', props: ['extraContent', 'inkBarAnimated', 'tabBarGutter', 'prefixCls',
'navWrapper', 'tabBarPosition', 'panels', 'activeKey'], 'navWrapper', 'tabBarPosition', 'panels', 'activeKey', 'prevIcon', 'nextIcon'],
render () { render () {
const props = { ...this.$props } const props = { ...this.$props }
const listeners = this.$listeners const listeners = this.$listeners