2018-09-13 13:23:13 +00:00
|
|
|
import omit from 'omit.js'
|
2018-01-12 09:06:01 +00:00
|
|
|
import BaseMixin from '../../_util/BaseMixin'
|
2018-09-05 13:28:54 +00:00
|
|
|
import PropTypes from '../../_util/vue-types'
|
|
|
|
import KeyCode from './KeyCode'
|
|
|
|
import { getOptionProps } from '../../_util/props-util'
|
|
|
|
import { cloneElement } from '../../_util/vnode'
|
|
|
|
|
|
|
|
function getDefaultActiveKey (props) {
|
2017-11-21 11:15:41 +00:00
|
|
|
let activeKey
|
2018-09-05 13:28:54 +00:00
|
|
|
const children = props.children
|
|
|
|
children.forEach((child) => {
|
2017-11-21 11:15:41 +00:00
|
|
|
if (child && !activeKey && !child.disabled) {
|
2018-09-05 13:28:54 +00:00
|
|
|
activeKey = child.key
|
2017-11-21 11:15:41 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
return activeKey
|
|
|
|
}
|
2018-09-05 13:28:54 +00:00
|
|
|
|
|
|
|
function activeKeyIsValid (props, key) {
|
|
|
|
const children = props.children
|
|
|
|
const keys = children.map(child => child && child.key)
|
|
|
|
return 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',
|
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: {
|
2018-09-05 13:28:54 +00:00
|
|
|
destroyInactiveTabPane: PropTypes.bool,
|
|
|
|
renderTabBar: PropTypes.func.isRequired,
|
|
|
|
renderTabContent: PropTypes.func.isRequired,
|
|
|
|
navWrapper: PropTypes.func.def(arg => arg),
|
|
|
|
children: PropTypes.any.def([]),
|
|
|
|
prefixCls: PropTypes.string.def('ant-tabs'),
|
|
|
|
tabBarPosition: PropTypes.string.def('top'),
|
|
|
|
activeKey: PropTypes.string,
|
|
|
|
defaultActiveKey: PropTypes.string,
|
|
|
|
__propsSymbol__: PropTypes.any,
|
2017-11-21 11:15:41 +00:00
|
|
|
},
|
|
|
|
data () {
|
2018-09-05 13:28:54 +00:00
|
|
|
const props = getOptionProps(this)
|
|
|
|
let activeKey
|
|
|
|
if ('activeKey' in props) {
|
|
|
|
activeKey = props.activeKey
|
|
|
|
} else if ('defaultActiveKey' in props) {
|
|
|
|
activeKey = props.defaultActiveKey
|
|
|
|
} else {
|
|
|
|
activeKey = getDefaultActiveKey(props)
|
|
|
|
}
|
2017-11-21 11:15:41 +00:00
|
|
|
return {
|
2018-09-05 13:28:54 +00:00
|
|
|
_activeKey: activeKey,
|
2017-11-21 11:15:41 +00:00
|
|
|
}
|
|
|
|
},
|
2018-09-05 13:28:54 +00:00
|
|
|
watch: {
|
|
|
|
__propsSymbol__ () {
|
|
|
|
const nextProps = getOptionProps(this)
|
|
|
|
if ('activeKey' in nextProps) {
|
|
|
|
this.setState({
|
|
|
|
_activeKey: nextProps.activeKey,
|
|
|
|
})
|
|
|
|
} else if (!activeKeyIsValid(nextProps, this.$data._activeKey)) {
|
|
|
|
// https://github.com/ant-design/ant-design/issues/7093
|
|
|
|
this.setState({
|
|
|
|
_activeKey: getDefaultActiveKey(nextProps),
|
|
|
|
})
|
2017-11-21 11:15:41 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
methods: {
|
2018-09-05 13:28:54 +00:00
|
|
|
onTabClick (activeKey, e) {
|
|
|
|
if (this.tabBar.componentOptions &&
|
|
|
|
this.tabBar.componentOptions.listeners &&
|
|
|
|
this.tabBar.componentOptions.listeners.tabClick) {
|
|
|
|
this.tabBar.componentOptions.listeners.tabClick(activeKey, e)
|
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)
|
2018-09-05 13:28:54 +00:00
|
|
|
this.onTabClick(nextKey)
|
2017-11-21 11:15:41 +00:00
|
|
|
} else if (eventKeyCode === KeyCode.LEFT || eventKeyCode === KeyCode.UP) {
|
|
|
|
e.preventDefault()
|
|
|
|
const previousKey = this.getNextActiveKey(false)
|
2018-09-05 13:28:54 +00:00
|
|
|
this.onTabClick(previousKey)
|
2017-11-21 11:15:41 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
setActiveKey (activeKey) {
|
2018-09-05 13:28:54 +00:00
|
|
|
if (this.$data._activeKey !== activeKey) {
|
|
|
|
const props = getOptionProps(this)
|
|
|
|
if (!('activeKey' in props)) {
|
|
|
|
this.setState({
|
|
|
|
_activeKey: activeKey,
|
|
|
|
})
|
2017-11-21 11:15:41 +00:00
|
|
|
}
|
2018-01-12 09:06:01 +00:00
|
|
|
this.__emit('change', activeKey)
|
2017-11-21 11:15:41 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
getNextActiveKey (next) {
|
2018-09-05 13:28:54 +00:00
|
|
|
const activeKey = this.$data._activeKey
|
2017-11-21 11:15:41 +00:00
|
|
|
const children = []
|
2018-09-05 13:28:54 +00:00
|
|
|
this.$props.children.forEach((c) => {
|
2017-12-01 10:48:16 +00:00
|
|
|
if (c && !c.disabled && c.disabled !== '') {
|
2017-11-21 11:15:41 +00:00
|
|
|
if (next) {
|
2018-09-05 13:28:54 +00:00
|
|
|
children.push(c)
|
2017-11-21 11:15:41 +00:00
|
|
|
} else {
|
2018-09-05 13:28:54 +00:00
|
|
|
children.unshift(c)
|
2017-11-21 11:15:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
const length = children.length
|
2018-09-05 13:28:54 +00:00
|
|
|
let ret = length && children[0].key
|
2017-11-21 11:15:41 +00:00
|
|
|
children.forEach((child, i) => {
|
2018-09-05 13:28:54 +00:00
|
|
|
if (child.key === activeKey) {
|
2017-11-21 11:15:41 +00:00
|
|
|
if (i === length - 1) {
|
2018-09-05 13:28:54 +00:00
|
|
|
ret = children[0].key
|
2017-11-21 11:15:41 +00:00
|
|
|
} else {
|
2018-09-05 13:28:54 +00:00
|
|
|
ret = children[i + 1].key
|
2017-11-21 11:15:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return ret
|
|
|
|
},
|
|
|
|
},
|
|
|
|
render () {
|
2018-09-05 13:28:54 +00:00
|
|
|
const props = this.$props
|
2017-11-21 11:15:41 +00:00
|
|
|
const {
|
|
|
|
prefixCls,
|
2018-09-05 13:28:54 +00:00
|
|
|
navWrapper,
|
2017-11-21 11:15:41 +00:00
|
|
|
tabBarPosition,
|
2018-09-05 13:28:54 +00:00
|
|
|
renderTabContent,
|
|
|
|
renderTabBar,
|
2017-11-21 11:15:41 +00:00
|
|
|
destroyInactiveTabPane,
|
2018-09-05 13:28:54 +00:00
|
|
|
} = props
|
|
|
|
const cls = {
|
|
|
|
[prefixCls]: 1,
|
|
|
|
[`${prefixCls}-${tabBarPosition}`]: 1,
|
2017-11-22 07:05:53 +00:00
|
|
|
}
|
2018-09-05 13:28:54 +00:00
|
|
|
|
|
|
|
this.tabBar = renderTabBar()
|
2017-11-22 07:05:53 +00:00
|
|
|
const contents = [
|
2018-09-05 13:28:54 +00:00
|
|
|
cloneElement(this.tabBar, {
|
|
|
|
props: {
|
|
|
|
prefixCls,
|
|
|
|
navWrapper,
|
|
|
|
tabBarPosition,
|
|
|
|
panels: props.children,
|
|
|
|
activeKey: this.$data._activeKey,
|
|
|
|
},
|
|
|
|
on: {
|
|
|
|
keydown: this.onNavKeyDown,
|
|
|
|
tabClick: this.onTabClick,
|
|
|
|
},
|
|
|
|
key: 'tabBar',
|
|
|
|
}),
|
|
|
|
cloneElement(renderTabContent(), {
|
|
|
|
props: {
|
|
|
|
prefixCls,
|
|
|
|
tabBarPosition,
|
|
|
|
activeKey: this.$data._activeKey,
|
|
|
|
destroyInactiveTabPane,
|
|
|
|
},
|
|
|
|
on: {
|
|
|
|
change: this.setActiveKey,
|
|
|
|
},
|
|
|
|
children: props.children,
|
|
|
|
key: 'tabContent',
|
|
|
|
}),
|
2017-11-22 07:05:53 +00:00
|
|
|
]
|
|
|
|
if (tabBarPosition === 'bottom') {
|
|
|
|
contents.reverse()
|
|
|
|
}
|
2017-11-21 11:15:41 +00:00
|
|
|
return (
|
2018-09-13 13:23:13 +00:00
|
|
|
<div {...{ on: omit(this.$listeners, ['change']), class: cls }}>
|
2017-11-22 07:05:53 +00:00
|
|
|
{contents}
|
2017-11-21 11:15:41 +00:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
},
|
|
|
|
}
|