pull/9/head
tangjinzhou 2017-11-22 15:05:53 +08:00
parent 3b6008151b
commit 7c02b84d21
6 changed files with 159 additions and 91 deletions

View File

@ -1,7 +1,9 @@
export default { export default {
saveRef (name) { methods: {
return node => { saveRef (name) {
this[name] = node return node => {
} this[name] = node
}
},
}, },
} }

View File

@ -1,12 +1,10 @@
<template>
<button :class="classes" :disabled="disabled"
@click="handleClick" @mouseout="mouseout" @mouseover="mouseover">
{{tab}}
</button>
</template>
<script> <script>
import RefMixin from './RefMixin'
import TabBarMixin from './TabBarMixin'
function noop () {
}
export default { export default {
mixins: [RefMixin, TabBarMixin],
name: 'TabBar', name: 'TabBar',
props: { props: {
prefixCls: { prefixCls: {
@ -15,61 +13,23 @@ export default {
}, },
tabBarPosition: { tabBarPosition: {
default: 'top', default: 'top',
validator (value) { type: String,
return ['top', 'bottom'].includes(value)
},
}, },
disabled: Boolean, disabled: Boolean,
onKeyDown: Function, onKeyDown: {
onTabClick: Function, default: noop,
type: Function,
},
onTabClick: {
default: noop,
type: Function,
},
activeKey: String, activeKey: String,
tab: String, panels: Array,
}, },
data () { render (createElement) {
return { const tabs = this.getTabs()
sizeMap: { return this.getRootNode(tabs, createElement)
large: 'lg',
small: 'sm',
},
clicked: false,
}
},
computed: {
classes () {
const { prefixCls, type, shape, size, loading, ghost, clicked, sizeMap } = this
const sizeCls = sizeMap[size] || ''
return {
[`${prefixCls}`]: true,
[`${prefixCls}-${type}`]: type,
[`${prefixCls}-${shape}`]: shape,
[`${prefixCls}-${sizeCls}`]: sizeCls,
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-clicked`]: clicked,
[`${prefixCls}-background-ghost`]: ghost || type === 'ghost',
}
},
},
methods: {
handleClick (event) {
if (this.clicked) {
return
}
this.clicked = true
clearTimeout(this.timeout)
this.timeout = setTimeout(() => (this.clicked = false), 500)
this.$emit('click', event)
},
mouseover (event) {
this.$emit('mouseover', event)
},
mouseout (event) {
this.$emit('mouseout', event)
},
},
beforeDestroy () {
if (this.timeout) {
clearTimeout(this.timeout)
}
}, },
} }
</script> </script>

View File

@ -0,0 +1,72 @@
export default {
methods: {
getTabs () {
const { panels: children, activeKey, prefixCls } = this
const rst = []
children.forEach((child) => {
if (!child) {
return
}
const key = child.pKey
let cls = activeKey === key ? `${prefixCls}-tab-active` : ''
cls += ` ${prefixCls}-tab`
if (child.disabled) {
cls += ` ${prefixCls}-tab-disabled`
} else {
}
const onClick = () => {
!child.disabled && this.onTabClick(key)
}
const ref = {}
if (activeKey === key) {
ref.ref = this.saveRef('activeTab')
}
rst.push(
<div
role='tab'
aria-disabled={child.disabled ? 'true' : 'false'}
aria-selected={activeKey === key ? 'true' : 'false'}
class={cls}
key={key}
onClick={onClick}
>
{child.tab}
</div>
)
})
return rst
},
getRootNode (contents, createElement) {
const {
prefixCls, onKeyDown, tabBarPosition, $slots,
} = this
const cls = {
[`${prefixCls}-bar`]: true,
}
const topOrBottom = (tabBarPosition === 'top' || tabBarPosition === 'bottom')
const tabBarExtraContentStyle = topOrBottom ? { float: 'right' } : {}
let children = contents
if ($slots.default) {
children = [
<div key='extra' class='`${prefixCls}-extra-content`' style={tabBarExtraContentStyle}>
{$slots.default}
</div>,
contents,
]
children = topOrBottom ? children : children.reverse()
}
return (
<div
role='tablist'
class={cls}
tabIndex='0'
ref={this.saveRef('root')}
onKeydown={onKeyDown}
>
{children}
</div>
)
},
},
}

View File

@ -13,31 +13,34 @@ export default {
name: 'TabPane', name: 'TabPane',
props: { props: {
pKey: [String, Number], pKey: [String, Number],
tab: [String, Number],
forceRender: Boolean, forceRender: Boolean,
// placeholder: [Function, String, Number], // placeholder: [Function, String, Number],
}, },
data () { data () {
const { prefixCls, destroyInactiveTabPane, activeKey } = this.$parent
return { return {
rootPrefixCls: prefixCls,
destroyInactiveTabPane,
active: this.pKey === activeKey,
} }
}, },
computed: { computed: {
classes () { classes () {
const { rootPrefixCls, active } = this const { $parent, active } = this
const prefixCls = `${rootPrefixCls}-tabpane` const prefixCls = `${$parent.prefixCls}-tabpane`
return { return {
[`${prefixCls}`]: true, [`${prefixCls}`]: true,
[`${prefixCls}-inactive`]: !active, [`${prefixCls}-inactive`]: !active,
[`${prefixCls}-active`]: active, [`${prefixCls}-active`]: active,
} }
}, },
active () {
const { activeKey } = this.$parent
return activeKey === this.pKey
},
isRender () { isRender () {
const { const {
destroyInactiveTabPane, active, active,
$parent,
} = this } = this
const destroyInactiveTabPane = $parent.destroyInactiveTabPane
this._isActived = this._isActived || active this._isActived = this._isActived || active
return destroyInactiveTabPane ? active : this._isActived return destroyInactiveTabPane ? active : this._isActived
}, },

View File

@ -19,6 +19,10 @@ function activeKeyIsValid (t, key) {
export default { export default {
name: 'Tabs', name: 'Tabs',
components: { Icon }, components: { Icon },
model: {
prop: 'activeKey',
event: 'change',
},
props: { props: {
prefixCls: { prefixCls: {
default: 'ant-tabs', default: 'ant-tabs',
@ -27,7 +31,7 @@ export default {
tabBarPosition: { tabBarPosition: {
default: 'top', default: 'top',
validator (value) { validator (value) {
return ['top', 'bottom'].includes(value) return ['top', 'bottom', 'left', 'right'].includes(value)
}, },
}, },
destroyInactiveTabPane: Boolean, destroyInactiveTabPane: Boolean,
@ -68,9 +72,10 @@ export default {
return activeKey return activeKey
}, },
onTabClick (activeKey) { onTabClick (activeKey) {
if (this.tabBar.props.onTabClick) { console.log('onTabClick', activeKey)
this.tabBar.props.onTabClick(activeKey) // if (this.tabBar.props.onTabClick) {
} // this.tabBar.props.onTabClick(activeKey)
// }
this.setActiveKey(activeKey) this.setActiveKey(activeKey)
}, },
@ -92,6 +97,7 @@ export default {
if (!('activeKey' in this)) { if (!('activeKey' in this)) {
this.stateActiveKey = activeKey this.stateActiveKey = activeKey
} }
// this.stateActiveKey = activeKey
this.$emit('change', activeKey) this.$emit('change', activeKey)
} }
}, },
@ -99,7 +105,8 @@ export default {
getNextActiveKey (next) { getNextActiveKey (next) {
const activeKey = this.stateActiveKey const activeKey = this.stateActiveKey
const children = [] const children = []
this.$slot.default.forEach((c) => { this.$slots.default.forEach(({ componentOptions = {}}) => {
const c = componentOptions.propsData
if (c && !c.disabled) { if (c && !c.disabled) {
if (next) { if (next) {
children.push(c) children.push(c)
@ -113,9 +120,9 @@ export default {
children.forEach((child, i) => { children.forEach((child, i) => {
if (child.pKey === activeKey) { if (child.pKey === activeKey) {
if (i === length - 1) { if (i === length - 1) {
ret = children[0].key ret = children[0].pKey
} else { } else {
ret = children[i + 1].key ret = children[i + 1].pKey
} }
} }
}) })
@ -137,17 +144,10 @@ export default {
$slots, $slots,
} = this } = this
const hasSlot = !!$slots.default const hasSlot = !!$slots.default
const tabBarProps = [] const panels = []
if (hasSlot) { if (hasSlot) {
$slots.default.forEach(tab => { $slots.default.forEach(tab => {
tab.data && tabBarProps.push( tab.componentOptions && panels.push(tab.componentOptions.propsData)
<TabBar
{...tab.data}
prefixCls={prefixCls}
onKeyDown={onNavKeyDown}
tabBarPosition={tabBarPosition}
onTabClick={onTabClick}
activeKey={stateActiveKey} />)
}) })
} }
const tabContentProps = { const tabContentProps = {
@ -158,15 +158,35 @@ export default {
destroyInactiveTabPane, destroyInactiveTabPane,
onChange: setActiveKey, onChange: setActiveKey,
key: 'tabContent', key: 'tabContent',
}} },
}
const tabBarProps = {
props: {
panels: panels,
prefixCls: prefixCls,
onKeyDown: onNavKeyDown,
tabBarPosition: tabBarPosition,
onTabClick: onTabClick,
activeKey: stateActiveKey,
key: 'tabBar',
},
}
const contents = [
<TabBar {...tabBarProps}>
{this.$slots.tabBarExtraContent}
</TabBar>,
<TabContent {...tabContentProps}>
{$slots.default}
</TabContent>,
]
if (tabBarPosition === 'bottom') {
contents.reverse()
}
return ( return (
<div <div
class={classes} class={classes}
> >
{tabBarProps} {contents}
<TabContent {...tabContentProps}>
{$slots.default}
</TabContent>
</div> </div>
) )
}, },

View File

@ -1,6 +1,7 @@
<template> <template>
<div> <div>
<Tabs activeKey="test1"> <Tabs v-model="activeKey">
<span slot="tabBarExtraContent">kkk</span>
<TabPane pKey="test1" tab="tab1">hello</TabPane> <TabPane pKey="test1" tab="tab1">hello</TabPane>
<TabPane pKey="test2" tab="tab2">world</TabPane> <TabPane pKey="test2" tab="tab2">world</TabPane>
</Tabs> </Tabs>
@ -9,6 +10,16 @@
<script> <script>
import { Tabs } from 'antd' import { Tabs } from 'antd'
export default { export default {
data () {
return {
activeKey: 'test1',
}
},
methods: {
tabBarExtraContent (h) {
return h('span', 'hhhh')
},
},
components: { components: {
Tabs, Tabs,
TabPane: Tabs.TabPane, TabPane: Tabs.TabPane,