ant-design-vue/components/tabs/src/Tabs.vue

228 lines
5.7 KiB
Vue
Raw Normal View History

2017-11-21 11:15:41 +00:00
<script>
2018-01-12 09:06:01 +00:00
import Icon from '../../icon'
2017-11-21 11:15:41 +00:00
import KeyCode from './KeyCode'
import TabContent from './TabContent'
2017-11-30 11:11:42 +00:00
import ScrollableInkTabBar from './ScrollableInkTabBar'
2018-01-12 09:06:01 +00:00
import hasProp from '../../_util/props-util'
import BaseMixin from '../../_util/BaseMixin'
2017-11-21 11:15:41 +00:00
function getDefaultActiveKey (t) {
let activeKey
2017-12-08 03:46:53 +00:00
t.$slots.default && t.$slots.default.forEach(({ componentOptions = {}, key: tabKey }) => {
2017-12-01 04:21:43 +00:00
const child = componentOptions.propsData
2017-11-21 11:15:41 +00:00
if (child && !activeKey && !child.disabled) {
2017-12-08 03:46:53 +00:00
activeKey = tabKey
2017-11-21 11:15:41 +00:00
}
})
return activeKey
}
function activeKeyIsValid (t, key) {
2017-12-08 03:46:53 +00:00
const keys = t.$slots.default && t.$slots.default.map(({ componentOptions = {}, key: tabKey }) => {
2017-12-01 04:21:43 +00:00
const child = componentOptions.propsData
if (child) {
2017-12-08 03:46:53 +00:00
return tabKey
2017-12-01 04:21:43 +00:00
}
})
return key !== undefined && keys.indexOf(key) >= 0
2017-11-21 11:15:41 +00:00
}
2018-01-12 09:06:01 +00:00
2017-11-21 11:15:41 +00:00
export default {
name: 'Tabs',
components: { Icon },
2017-11-22 07:05:53 +00:00
model: {
prop: 'activeKey',
event: 'change',
},
2018-01-12 09:06:01 +00:00
mixins: [BaseMixin],
2017-11-21 11:15:41 +00:00
props: {
prefixCls: {
default: 'ant-tabs',
type: String,
},
tabBarPosition: {
default: 'top',
validator (value) {
2017-11-22 07:05:53 +00:00
return ['top', 'bottom', 'left', 'right'].includes(value)
2017-11-21 11:15:41 +00:00
},
},
2017-11-30 11:11:42 +00:00
tabBarProps: Object,
2017-12-01 04:21:43 +00:00
tabContentProps: Object,
2017-11-21 11:15:41 +00:00
destroyInactiveTabPane: Boolean,
activeKey: String,
defaultActiveKey: String,
2017-12-01 10:48:16 +00:00
type: {
validator (value) {
return ['line', 'card', 'editable-card'].includes(value)
},
},
2017-11-21 11:15:41 +00:00
},
data () {
return {
stateActiveKey: this.getStateActiveKey(),
}
},
computed: {
classes () {
const { prefixCls, tabBarPosition } = this
return {
[`${prefixCls}`]: true,
[`${prefixCls}-${tabBarPosition}`]: true,
}
},
},
beforeUpdate () {
2017-12-01 04:21:43 +00:00
if (this.activeKey) {
2017-11-21 11:15:41 +00:00
this.stateActiveKey = this.activeKey
} else if (!activeKeyIsValid(this, this.stateActiveKey)) {
this.stateActiveKey = getDefaultActiveKey(this)
}
},
methods: {
getStateActiveKey () {
let activeKey
2017-12-01 04:21:43 +00:00
if (this.activeKey) {
2017-11-21 11:15:41 +00:00
activeKey = this.activeKey
2017-12-01 04:21:43 +00:00
} else if (this.defaultActiveKey) {
2017-11-21 11:15:41 +00:00
activeKey = this.defaultActiveKey
} else {
activeKey = getDefaultActiveKey(this)
}
return activeKey
},
2017-12-01 10:48:16 +00:00
handleTabClick (activeKey) {
2018-01-12 09:06:01 +00:00
this.__emit('tabClick', activeKey)
2017-11-21 11:15:41 +00:00
this.setActiveKey(activeKey)
},
onNavKeyDown (e) {
const eventKeyCode = e.keyCode
if (eventKeyCode === KeyCode.RIGHT || eventKeyCode === KeyCode.DOWN) {
e.preventDefault()
const nextKey = this.getNextActiveKey(true)
2017-12-01 10:48:16 +00:00
this.handleTabClick(nextKey)
2017-11-21 11:15:41 +00:00
} else if (eventKeyCode === KeyCode.LEFT || eventKeyCode === KeyCode.UP) {
e.preventDefault()
const previousKey = this.getNextActiveKey(false)
2017-12-01 10:48:16 +00:00
this.handleTabClick(previousKey)
2017-11-21 11:15:41 +00:00
}
},
setActiveKey (activeKey) {
if (this.stateActiveKey !== activeKey) {
2017-12-27 10:15:11 +00:00
if (!hasProp(this, 'activeKey')) {
2017-11-21 11:15:41 +00:00
this.stateActiveKey = activeKey
}
2018-01-12 09:06:01 +00:00
this.__emit('change', activeKey)
2017-11-21 11:15:41 +00:00
}
},
getNextActiveKey (next) {
const activeKey = this.stateActiveKey
const children = []
2017-12-08 03:46:53 +00:00
this.$slots.default && this.$slots.default.forEach(({ componentOptions = {}, key: tabKey }) => {
2017-11-22 07:05:53 +00:00
const c = componentOptions.propsData
2017-12-08 03:46:53 +00:00
2017-12-01 10:48:16 +00:00
if (c && !c.disabled && c.disabled !== '') {
2017-11-21 11:15:41 +00:00
if (next) {
2017-12-08 03:46:53 +00:00
children.push({ ...c, tabKey })
2017-11-21 11:15:41 +00:00
} else {
2017-12-08 03:46:53 +00:00
children.unshift({ ...c, tabKey })
2017-11-21 11:15:41 +00:00
}
}
})
const length = children.length
2017-12-08 03:46:53 +00:00
let ret = length && children[0].tabKey
2017-11-21 11:15:41 +00:00
children.forEach((child, i) => {
2017-12-01 04:21:43 +00:00
if (child.tabKey === activeKey) {
2017-11-21 11:15:41 +00:00
if (i === length - 1) {
2017-12-01 04:21:43 +00:00
ret = children[0].tabKey
2017-11-21 11:15:41 +00:00
} else {
2017-12-01 04:21:43 +00:00
ret = children[i + 1].tabKey
2017-11-21 11:15:41 +00:00
}
}
})
return ret
},
},
beforeDestroy () {
},
render () {
const {
prefixCls,
tabBarPosition,
destroyInactiveTabPane,
onNavKeyDown,
2017-12-01 10:48:16 +00:00
handleTabClick,
2017-11-21 11:15:41 +00:00
stateActiveKey,
classes,
setActiveKey,
$slots,
} = this
2017-11-22 07:05:53 +00:00
const panels = []
2017-12-07 07:05:33 +00:00
2017-12-08 03:46:53 +00:00
$slots.default && $slots.default.forEach(({ componentOptions, key: tabKey }) => {
if (componentOptions) {
if (componentOptions.propsData.tab === undefined) {
2018-01-19 03:47:06 +00:00
const tab = (componentOptions.children || []).filter(({ data = {}}) => data.slot === 'tab')
componentOptions.propsData.tab = tab
2017-12-08 03:46:53 +00:00
}
panels.push({ ...componentOptions.propsData, tabKey })
}
2017-12-07 07:05:33 +00:00
})
2017-11-21 11:15:41 +00:00
const tabContentProps = {
props: {
2018-01-12 09:06:01 +00:00
...this.tabContentProps.props,
2017-11-21 11:15:41 +00:00
prefixCls,
tabBarPosition,
activeKey: stateActiveKey,
destroyInactiveTabPane,
2018-01-12 09:06:01 +00:00
// onChange: setActiveKey,
},
on: {
change: setActiveKey,
2017-11-22 07:05:53 +00:00
},
}
const tabBarProps = {
props: {
2018-01-12 09:06:01 +00:00
...this.tabBarProps.props,
2017-11-22 07:05:53 +00:00
panels: panels,
prefixCls: prefixCls,
tabBarPosition: tabBarPosition,
activeKey: stateActiveKey,
},
2017-12-01 04:21:43 +00:00
style: this.tabBarProps.style || {},
2018-01-12 09:06:01 +00:00
on: {
...this.tabBarProps.on,
keydown: onNavKeyDown,
tabClick: handleTabClick,
},
2017-11-22 07:05:53 +00:00
}
const contents = [
2017-12-14 02:13:30 +00:00
<ScrollableInkTabBar
{...tabBarProps}
key='tabBar'
>
2017-12-12 03:08:56 +00:00
{$slots.tabBarExtraContent ? <template slot='extraContent'>
2017-12-07 07:05:33 +00:00
{$slots.tabBarExtraContent}
2017-12-12 03:08:56 +00:00
</template> : null}
2017-12-07 07:05:33 +00:00
</ScrollableInkTabBar>,
2017-12-14 02:13:30 +00:00
<TabContent
{...tabContentProps}
key='tabContent'
>
2017-11-22 07:05:53 +00:00
{$slots.default}
</TabContent>,
]
if (tabBarPosition === 'bottom') {
contents.reverse()
}
2017-11-21 11:15:41 +00:00
return (
<div
class={classes}
>
2017-11-22 07:05:53 +00:00
{contents}
2017-11-21 11:15:41 +00:00
</div>
)
},
}
</script>