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

189 lines
4.9 KiB
Vue

import omit from 'omit.js'
import BaseMixin from '../../_util/BaseMixin'
import PropTypes from '../../_util/vue-types'
import KeyCode from './KeyCode'
import { getOptionProps } from '../../_util/props-util'
import { cloneElement } from '../../_util/vnode'
function getDefaultActiveKey (props) {
let activeKey
const children = props.children
children.forEach((child) => {
if (child && !activeKey && !child.disabled) {
activeKey = child.key
}
})
return activeKey
}
function activeKeyIsValid (props, key) {
const children = props.children
const keys = children.map(child => child && child.key)
return keys.indexOf(key) >= 0
}
export default {
name: 'Tabs',
model: {
prop: 'activeKey',
event: 'change',
},
mixins: [BaseMixin],
props: {
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,
},
data () {
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)
}
return {
_activeKey: activeKey,
}
},
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),
})
}
},
},
methods: {
onTabClick (activeKey, e) {
if (this.tabBar.componentOptions &&
this.tabBar.componentOptions.listeners &&
this.tabBar.componentOptions.listeners.tabClick) {
this.tabBar.componentOptions.listeners.tabClick(activeKey, e)
}
this.setActiveKey(activeKey)
},
onNavKeyDown (e) {
const eventKeyCode = e.keyCode
if (eventKeyCode === KeyCode.RIGHT || eventKeyCode === KeyCode.DOWN) {
e.preventDefault()
const nextKey = this.getNextActiveKey(true)
this.onTabClick(nextKey)
} else if (eventKeyCode === KeyCode.LEFT || eventKeyCode === KeyCode.UP) {
e.preventDefault()
const previousKey = this.getNextActiveKey(false)
this.onTabClick(previousKey)
}
},
setActiveKey (activeKey) {
if (this.$data._activeKey !== activeKey) {
const props = getOptionProps(this)
if (!('activeKey' in props)) {
this.setState({
_activeKey: activeKey,
})
}
this.__emit('change', activeKey)
}
},
getNextActiveKey (next) {
const activeKey = this.$data._activeKey
const children = []
this.$props.children.forEach((c) => {
if (c && !c.disabled && c.disabled !== '') {
if (next) {
children.push(c)
} else {
children.unshift(c)
}
}
})
const length = children.length
let ret = length && children[0].key
children.forEach((child, i) => {
if (child.key === activeKey) {
if (i === length - 1) {
ret = children[0].key
} else {
ret = children[i + 1].key
}
}
})
return ret
},
},
render () {
const props = this.$props
const {
prefixCls,
navWrapper,
tabBarPosition,
renderTabContent,
renderTabBar,
destroyInactiveTabPane,
} = props
const cls = {
[prefixCls]: 1,
[`${prefixCls}-${tabBarPosition}`]: 1,
}
this.tabBar = renderTabBar()
const contents = [
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',
}),
]
if (tabBarPosition === 'bottom') {
contents.reverse()
}
return (
<div {...{ on: omit(this.$listeners, ['change']), class: cls }}>
{contents}
</div>
)
},
}