add demo
							parent
							
								
									350001ea14
								
							
						
					
					
						commit
						d2d2f5b173
					
				|  | @ -8,7 +8,7 @@ export default { | |||
|   render (h) { | ||||
|     const inkBarNode = this.getInkBarNode() | ||||
|     const tabs = this.getTabs(h) | ||||
|     return this.getRootNode([inkBarNode, tabs]) | ||||
|     return this.getRootNode([inkBarNode, tabs], h) | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ export default { | |||
|     const inkBarNode = this.getInkBarNode() | ||||
|     const tabs = this.getTabs(h) | ||||
|     const scrollbarNode = this.getScrollBarNode([inkBarNode, tabs]) | ||||
|     return this.getRootNode(scrollbarNode) | ||||
|     return this.getRootNode(scrollbarNode, h) | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ export default { | |||
|     const inkBarNode = this.getInkBarNode() | ||||
|     const tabs = this.getTabs(h) | ||||
|     const scrollbarNode = this.getScrollBarNode([inkBarNode, tabs]) | ||||
|     return this.getRootNode(scrollbarNode) | ||||
|     return this.getRootNode(scrollbarNode, h) | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  |  | |||
|  | @ -27,20 +27,8 @@ export default { | |||
|     this.resizeEvent = addDOMEventListener(window, 'resize', debouncedResize) | ||||
|   }, | ||||
| 
 | ||||
|   updated (prevProps) { | ||||
|     const props = this.$props | ||||
|     if (prevProps && prevProps.tabBarPosition !== props.tabBarPosition) { | ||||
|       this.setOffset(0) | ||||
|       return | ||||
|     } | ||||
|     const nextPrev = this.setNextPrev() | ||||
|     // wait next, prev show hide
 | ||||
|     if (this.isNextPrevShown(this) !== this.isNextPrevShown(nextPrev)) { | ||||
|       Object.assign(this, this.scrollToActiveTab) | ||||
|     } else if (!prevProps || props.activeKey !== prevProps.activeKey) { | ||||
|       // can not use props.activeKey
 | ||||
|       this.scrollToActiveTab() | ||||
|     } | ||||
|   updated () { | ||||
|     this.updatedCal() | ||||
|   }, | ||||
| 
 | ||||
|   beforeDestroy () { | ||||
|  | @ -48,9 +36,17 @@ export default { | |||
|       this.resizeEvent.remove() | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     tabBarPosition (val) { | ||||
|       this.setOffset(0) | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     updatedCal () { | ||||
| 
 | ||||
|       this.setNextPrev() | ||||
|       this.$nextTick(() => { | ||||
|         this.scrollToActiveTab() | ||||
|       }) | ||||
|     }, | ||||
|     setNextPrev () { | ||||
|       const navNode = this.$refs.nav | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| import Icon from '../icon' | ||||
| export default { | ||||
|   props: { | ||||
|     prefixCls: { | ||||
|  | @ -19,6 +20,16 @@ export default { | |||
|     }, | ||||
|     activeKey: String, | ||||
|     panels: Array, | ||||
|     extraContent: [String, Number, Function], | ||||
|     hideAdd: Boolean, | ||||
|     removeTab: { | ||||
|       default: () => {}, | ||||
|       type: Function, | ||||
|     }, | ||||
|     createNewTab: { | ||||
|       default: () => {}, | ||||
|       type: Function, | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     getTabs (h) { | ||||
|  | @ -28,33 +39,46 @@ export default { | |||
|         if (!child) { | ||||
|           return | ||||
|         } | ||||
|         let { disabled, closable } = child | ||||
|         const { tabKey, tab } = child | ||||
|         // componentOptions.propsData中获取的值disabled没有根据类型初始化, 会出现空字符串
 | ||||
|         child.disabled = child.disabled === '' || child.disabled | ||||
|         const key = child.tabKey | ||||
|         let cls = activeKey === key ? `${prefixCls}-tab-active` : '' | ||||
|         disabled = disabled === '' || disabled | ||||
|         let cls = activeKey === tabKey ? `${prefixCls}-tab-active` : '' | ||||
|         cls += ` ${prefixCls}-tab` | ||||
|         if (child.disabled) { | ||||
|         if (disabled) { | ||||
|           cls += ` ${prefixCls}-tab-disabled` | ||||
|         } else { | ||||
|         } | ||||
|         const onClick = () => { | ||||
|           !child.disabled && this.onTabClick(key) | ||||
|           !disabled && this.onTabClick(tabKey) | ||||
|         } | ||||
|         // const ref = {}
 | ||||
|         // if (activeKey === key) {
 | ||||
|         //   ref.ref = this.saveRef('activeTab')
 | ||||
|         // }
 | ||||
| 
 | ||||
|         let tabC = typeof tab === 'function' ? child.tab(h, tabKey) : tab | ||||
|         if (this.$parent.type === 'editable-card') { | ||||
|           closable = closable === undefined ? true : closable === '' || closable | ||||
|           const closeIcon = closable ? ( | ||||
|             <Icon | ||||
|               type='close' | ||||
|               onClick={e => this.removeTab(tabKey, e)} | ||||
|             /> | ||||
|           ) : null | ||||
|           tabC = <div class={closable ? undefined : `${prefixCls}-tab-unclosable`}> | ||||
|             {tabC} | ||||
|             {closeIcon} | ||||
|           </div> | ||||
|         } | ||||
| 
 | ||||
|         rst.push( | ||||
|           <div | ||||
|             role='tab' | ||||
|             aria-disabled={child.disabled ? 'true' : 'false'} | ||||
|             aria-selected={activeKey === key ? 'true' : 'false'} | ||||
|             aria-disabled={disabled ? 'true' : 'false'} | ||||
|             aria-selected={activeKey === tabKey ? 'true' : 'false'} | ||||
|             class={cls} | ||||
|             key={key} | ||||
|             key={tabKey} | ||||
|             onClick={onClick} | ||||
|             ref={activeKey === key ? 'activeTab' : undefined} | ||||
|             ref={activeKey === tabKey ? 'activeTab' : undefined} | ||||
|           > | ||||
|             {typeof child.tab === 'function' ? child.tab(h, key) : child.tab} | ||||
|             {tabC} | ||||
|           </div> | ||||
|         ) | ||||
|       }) | ||||
|  | @ -63,23 +87,35 @@ export default { | |||
|     }, | ||||
|     getRootNode (contents, createElement) { | ||||
|       const { | ||||
|         prefixCls, onKeyDown, tabBarPosition, $slots, | ||||
|         prefixCls, onKeyDown, tabBarPosition, hideAdd, | ||||
|       } = this | ||||
|       let extraContent = this.extraContent | ||||
|       const tabsType = this.$parent.type | ||||
|       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() | ||||
|       extraContent = typeof extraContent === 'function' ? extraContent(createElement) : extraContent | ||||
| 
 | ||||
|       if (tabsType === 'editable-card' && !hideAdd) { | ||||
|         extraContent = ( | ||||
|           <span> | ||||
|             <Icon type='plus' class={`${prefixCls}-new-tab`} onClick={this.createNewTab} /> | ||||
|             {extraContent} | ||||
|           </span> | ||||
|         ) | ||||
|       } | ||||
| 
 | ||||
|       children = [ | ||||
|         <div key='extra' class={`${prefixCls}-extra-content`} style={tabBarExtraContentStyle}> | ||||
|           {extraContent} | ||||
|         </div>, | ||||
|         contents, | ||||
|       ] | ||||
|       children = topOrBottom ? children : children.reverse() | ||||
| 
 | ||||
|       return ( | ||||
|         <div | ||||
|           role='tablist' | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
|     :aria-hidden="active ? 'false' : 'true'" | ||||
|     :class="classes" | ||||
|   > | ||||
|     <slot v-if="isRender || forceRender"> | ||||
|     <slot v-if="isRender"> | ||||
|     </slot> | ||||
|   </div> | ||||
| </template> | ||||
|  | @ -14,12 +14,10 @@ export default { | |||
|   props: { | ||||
|     tabKey: [String, Number], | ||||
|     tab: [String, Number, Function], | ||||
|     forceRender: Boolean, | ||||
|     disabled: Boolean, | ||||
|     // placeholder: [Function, String, Number], | ||||
|     closable: Boolean, | ||||
|   }, | ||||
|   data () { | ||||
|     console.log(this.disabled) | ||||
|     return { | ||||
|     } | ||||
|   }, | ||||
|  |  | |||
|  | @ -45,6 +45,13 @@ export default { | |||
|     destroyInactiveTabPane: Boolean, | ||||
|     activeKey: String, | ||||
|     defaultActiveKey: String, | ||||
|     type: { | ||||
|       validator (value) { | ||||
|         return ['line', 'card', 'editable-card'].includes(value) | ||||
|       }, | ||||
|     }, | ||||
|     onChange: { type: Function, default: () => {} }, | ||||
|     onTabClick: { type: Function, default: () => {} }, | ||||
|   }, | ||||
|   data () { | ||||
|     return { | ||||
|  | @ -79,11 +86,8 @@ export default { | |||
|       } | ||||
|       return activeKey | ||||
|     }, | ||||
|     onTabClick (activeKey) { | ||||
|       console.log('onTabClick', activeKey) | ||||
|       // if (this.tabBar.props.onTabClick) { | ||||
|       //   this.tabBar.props.onTabClick(activeKey) | ||||
|       // } | ||||
|     handleTabClick (activeKey) { | ||||
|       this.onTabClick(activeKey) | ||||
|       this.setActiveKey(activeKey) | ||||
|     }, | ||||
| 
 | ||||
|  | @ -92,11 +96,11 @@ export default { | |||
|       if (eventKeyCode === KeyCode.RIGHT || eventKeyCode === KeyCode.DOWN) { | ||||
|         e.preventDefault() | ||||
|         const nextKey = this.getNextActiveKey(true) | ||||
|         this.onTabClick(nextKey) | ||||
|         this.handleTabClick(nextKey) | ||||
|       } else if (eventKeyCode === KeyCode.LEFT || eventKeyCode === KeyCode.UP) { | ||||
|         e.preventDefault() | ||||
|         const previousKey = this.getNextActiveKey(false) | ||||
|         this.onTabClick(previousKey) | ||||
|         this.handleTabClick(previousKey) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|  | @ -105,8 +109,7 @@ export default { | |||
|         if (!this.activeKey) { | ||||
|           this.stateActiveKey = activeKey | ||||
|         } | ||||
|         // this.stateActiveKey = activeKey | ||||
|         this.$emit('change', activeKey) | ||||
|         this.onChange(activeKey) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|  | @ -115,7 +118,7 @@ export default { | |||
|       const children = [] | ||||
|       this.$slots.default.forEach(({ componentOptions = {}}) => { | ||||
|         const c = componentOptions.propsData | ||||
|         if (c && !c.disabled) { | ||||
|         if (c && !c.disabled && c.disabled !== '') { | ||||
|           if (next) { | ||||
|             children.push(c) | ||||
|           } else { | ||||
|  | @ -145,7 +148,7 @@ export default { | |||
|       tabBarPosition, | ||||
|       destroyInactiveTabPane, | ||||
|       onNavKeyDown, | ||||
|       onTabClick, | ||||
|       handleTabClick, | ||||
|       stateActiveKey, | ||||
|       classes, | ||||
|       setActiveKey, | ||||
|  | @ -176,16 +179,14 @@ export default { | |||
|         prefixCls: prefixCls, | ||||
|         onKeyDown: onNavKeyDown, | ||||
|         tabBarPosition: tabBarPosition, | ||||
|         onTabClick: onTabClick, | ||||
|         onTabClick: handleTabClick, | ||||
|         activeKey: stateActiveKey, | ||||
|         key: 'tabBar', | ||||
|       }, | ||||
|       style: this.tabBarProps.style || {}, | ||||
|     } | ||||
|     const contents = [ | ||||
|       <ScrollableInkTabBar {...tabBarProps}> | ||||
|         {this.$slots.tabBarExtraContent} | ||||
|       </ScrollableInkTabBar>, | ||||
|       <ScrollableInkTabBar {...tabBarProps} />, | ||||
|       <TabContent {...tabContentProps}> | ||||
|         {$slots.default} | ||||
|       </TabContent>, | ||||
|  |  | |||
|  | @ -0,0 +1,69 @@ | |||
| <template> | ||||
|   <div class="card-container"> | ||||
|     <Tabs type="card"> | ||||
|       <TabPane tab="Tab Title 1" tabKey="1"> | ||||
|         <p>Content of Tab Pane 1</p> | ||||
|         <p>Content of Tab Pane 1</p> | ||||
|         <p>Content of Tab Pane 1</p> | ||||
|       </TabPane> | ||||
|       <TabPane tab="Tab Title 2" tabKey="2"> | ||||
|         <p>Content of Tab Pane 2</p> | ||||
|         <p>Content of Tab Pane 2</p> | ||||
|         <p>Content of Tab Pane 2</p> | ||||
|       </TabPane> | ||||
|       <TabPane tab="Tab Title 3" tabKey="3"> | ||||
|         <p>Content of Tab Pane 3</p> | ||||
|         <p>Content of Tab Pane 3</p> | ||||
|         <p>Content of Tab Pane 3</p> | ||||
|       </TabPane> | ||||
|     </Tabs> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import { Tabs } from 'antd' | ||||
| export default { | ||||
|   data () { | ||||
|     return { | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     callback (key) { | ||||
|       console.log(key) | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     Tabs, | ||||
|     TabPane: Tabs.TabPane, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
| <style> | ||||
| .card-container { | ||||
|   background: #F5F5F5; | ||||
|   overflow: hidden; | ||||
|   padding: 24px; | ||||
| } | ||||
| .card-container > .ant-tabs-card > .ant-tabs-content { | ||||
|   height: 120px; | ||||
|   margin-top: -16px; | ||||
| } | ||||
| 
 | ||||
| .card-container > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane { | ||||
|   background: #fff; | ||||
|   padding: 16px; | ||||
| } | ||||
| 
 | ||||
| .card-container > .ant-tabs-card > .ant-tabs-bar { | ||||
|   border-color: #fff; | ||||
| } | ||||
| 
 | ||||
| .card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab { | ||||
|   border-color: transparent; | ||||
|   background: transparent; | ||||
| } | ||||
| 
 | ||||
| .card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active { | ||||
|   border-color: #fff; | ||||
|   background: #fff; | ||||
| } | ||||
| </style> | ||||
|  | @ -0,0 +1,25 @@ | |||
| <template> | ||||
|   <Tabs @change="callback" type="card"> | ||||
|     <TabPane tab="Tab 1" tabKey="1">Content of Tab Pane 1</TabPane> | ||||
|     <TabPane tab="Tab 2" tabKey="2">Content of Tab Pane 2</TabPane> | ||||
|     <TabPane tab="Tab 3" tabKey="3">Content of Tab Pane 3</TabPane> | ||||
|   </Tabs> | ||||
| </template> | ||||
| <script> | ||||
| import { Tabs } from 'antd' | ||||
| export default { | ||||
|   data () { | ||||
|     return { | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     callback (key) { | ||||
|       console.log(key) | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     Tabs, | ||||
|     TabPane: Tabs.TabPane, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | @ -0,0 +1,69 @@ | |||
| <template> | ||||
| <div> | ||||
|     <div :style="{ marginBottom: '16px' }"> | ||||
|       <AntButton @click="add">ADD</AntButton> | ||||
|     </div> | ||||
|     <Tabs | ||||
|       hideAdd | ||||
|       v-model="activeKey" | ||||
|       type="editable-card" | ||||
|       @edit="onEdit" | ||||
|     > | ||||
|     <TabPane v-for="pane in panes" :tab="pane.title" :key="pane.key" :tabKey="pane.key" :closable="pane.closable"> | ||||
|       {{pane.content}} | ||||
|     </TabPane> | ||||
|   </Tabs> | ||||
|       </div> | ||||
| 
 | ||||
| </template> | ||||
| <script> | ||||
| import { Tabs, Button } from 'antd' | ||||
| export default { | ||||
|   data () { | ||||
|     const panes = [ | ||||
|       { title: 'Tab 1', content: 'Content of Tab 1', key: '1' }, | ||||
|       { title: 'Tab 2', content: 'Content of Tab 2', key: '2' }, | ||||
|     ] | ||||
|     return { | ||||
|       activeKey: panes[0].key, | ||||
|       panes, | ||||
|       newTabIndex: 0, | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     callback (key) { | ||||
|       console.log(key) | ||||
|     }, | ||||
|     onEdit (targetKey, action) { | ||||
|       this[action](targetKey) | ||||
|     }, | ||||
|     add () { | ||||
|       const panes = this.panes | ||||
|       const activeKey = `newTab${this.newTabIndex++}` | ||||
|       panes.push({ title: 'New Tab', content: 'Content of new Tab', key: activeKey }) | ||||
|       this.panes = panes | ||||
|       this.activeKey = activeKey | ||||
|     }, | ||||
|     remove (targetKey) { | ||||
|       let activeKey = this.activeKey | ||||
|       let lastIndex | ||||
|       this.panes.forEach((pane, i) => { | ||||
|         if (pane.key === targetKey) { | ||||
|           lastIndex = i - 1 | ||||
|         } | ||||
|       }) | ||||
|       const panes = this.panes.filter(pane => pane.key !== targetKey) | ||||
|       if (lastIndex >= 0 && activeKey === targetKey) { | ||||
|         activeKey = panes[lastIndex].key | ||||
|       } | ||||
|       this.panes = panes | ||||
|       this.activeKey = activeKey | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     Tabs, | ||||
|     TabPane: Tabs.TabPane, | ||||
|     AntButton: Button, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | @ -0,0 +1,61 @@ | |||
| <template> | ||||
|   <Tabs | ||||
|     v-model="activeKey" | ||||
|     type="editable-card" | ||||
|     @edit="onEdit" | ||||
|   > | ||||
|     <TabPane v-for="pane in panes" :tab="pane.title" :key="pane.key" :tabKey="pane.key" :closable="pane.closable"> | ||||
|       {{pane.content}} | ||||
|     </TabPane> | ||||
|   </Tabs> | ||||
| </template> | ||||
| <script> | ||||
| import { Tabs } from 'antd' | ||||
| export default { | ||||
|   data () { | ||||
|     const panes = [ | ||||
|       { title: 'Tab 1', content: 'Content of Tab 1', key: '1', closable: false }, | ||||
|       { title: 'Tab 2', content: 'Content of Tab 2', key: '2' }, | ||||
|     ] | ||||
|     return { | ||||
|       activeKey: panes[0].key, | ||||
|       panes, | ||||
|       newTabIndex: 0, | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     callback (key) { | ||||
|       console.log(key) | ||||
|     }, | ||||
|     onEdit (targetKey, action) { | ||||
|       this[action](targetKey) | ||||
|     }, | ||||
|     add () { | ||||
|       const panes = this.panes | ||||
|       const activeKey = `newTab${this.newTabIndex++}` | ||||
|       panes.push({ title: 'New Tab', content: 'Content of new Tab', key: activeKey }) | ||||
|       this.panes = panes | ||||
|       this.activeKey = activeKey | ||||
|     }, | ||||
|     remove (targetKey) { | ||||
|       let activeKey = this.activeKey | ||||
|       let lastIndex | ||||
|       this.panes.forEach((pane, i) => { | ||||
|         if (pane.key === targetKey) { | ||||
|           lastIndex = i - 1 | ||||
|         } | ||||
|       }) | ||||
|       const panes = this.panes.filter(pane => pane.key !== targetKey) | ||||
|       if (lastIndex >= 0 && activeKey === targetKey) { | ||||
|         activeKey = panes[lastIndex].key | ||||
|       } | ||||
|       this.panes = panes | ||||
|       this.activeKey = activeKey | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     Tabs, | ||||
|     TabPane: Tabs.TabPane, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | @ -0,0 +1,21 @@ | |||
| <template> | ||||
|   <Tabs :tabBarExtraContent="operations"> | ||||
|     <TabPane tab="Tab 1" tabKey="1">Content of tab 1</TabPane> | ||||
|     <TabPane tab="Tab 2" tabKey="2">Content of tab 2</TabPane> | ||||
|     <TabPane tab="Tab 3" tabKey="3">Content of tab 3</TabPane> | ||||
|   </Tabs> | ||||
| </template> | ||||
| <script> | ||||
| import { Tabs, Button } from 'antd' | ||||
| export default { | ||||
|   methods: { | ||||
|     operations (h) { | ||||
|       return h('span', [<Button>Extra Action</Button>]) | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     Tabs, | ||||
|     TabPane: Tabs.TabPane, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | @ -0,0 +1,54 @@ | |||
| <template> | ||||
|   <div> | ||||
|     <h1>Basic</h1> | ||||
|     <Basic /> | ||||
|     <h1>CardTop</h1> | ||||
|     <CardTop /> | ||||
|     <h1>Card</h1> | ||||
|     <Card /> | ||||
|     <h1>CustomAddTrigger</h1> | ||||
|     <CustomAddTrigger /> | ||||
|     <h1>Disabled</h1> | ||||
|     <Disabled /> | ||||
|     <h1>EditableCard</h1> | ||||
|     <EditableCard /> | ||||
|     <h1>Extra</h1> | ||||
|     <Extra /> | ||||
|     <h1>Icon</h1> | ||||
|     <Icon /> | ||||
|     <h1>Position</h1> | ||||
|     <Position /> | ||||
|     <h1>Size</h1> | ||||
|     <Size /> | ||||
|     <h1>Slide</h1> | ||||
|     <Slide/> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import Basic from './basic' | ||||
| import CardTop from './card-top' | ||||
| import Card from './card' | ||||
| import CustomAddTrigger from './custom-add-trigger' | ||||
| import Disabled from './disabled' | ||||
| import EditableCard from './editable-card' | ||||
| import Extra from './extra' | ||||
| import Icon from './icon' | ||||
| import Position from './position' | ||||
| import Size from './size' | ||||
| import Slide from './slide' | ||||
| export default { | ||||
|   components: { | ||||
|     Basic, | ||||
|     CardTop, | ||||
|     Card, | ||||
|     CustomAddTrigger, | ||||
|     Disabled, | ||||
|     EditableCard, | ||||
|     Extra, | ||||
|     Icon, | ||||
|     Position, | ||||
|     Size, | ||||
|     Slide, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | @ -0,0 +1,38 @@ | |||
| <template> | ||||
|   <div style="width: 500px"> | ||||
|     <RadioGroup v-model="tabPosition" style="margin:8px"> | ||||
|       <RadioButton value="top">top</RadioButton> | ||||
|       <RadioButton value="bottom">bottom</RadioButton> | ||||
|       <RadioButton value="left">left</RadioButton> | ||||
|       <RadioButton value="right">right</RadioButton> | ||||
|     </RadioGroup> | ||||
|     <Tabs defaultActiveKey="1" :tabPosition="tabPosition"> | ||||
|       <TabPane tab="Tab 1" tabKey="1">Content of Tab 1</TabPane> | ||||
|       <TabPane tab="Tab 2" tabKey="2">Content of Tab 2</TabPane> | ||||
|       <TabPane tab="Tab 3" tabKey="3">Content of Tab 3</TabPane> | ||||
|     </Tabs> | ||||
|   </div> | ||||
| 
 | ||||
| </template> | ||||
| <script> | ||||
| import { Tabs, Radio } from 'antd' | ||||
| export default { | ||||
|   data () { | ||||
|     return { | ||||
|       tabPosition: 'top', | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     callback (val) { | ||||
|       console.log(val) | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     Tabs, | ||||
|     TabPane: Tabs.TabPane, | ||||
|     Radio, | ||||
|     RadioGroup: Radio.Group, | ||||
|     RadioButton: Radio.Button, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | @ -0,0 +1,16 @@ | |||
| <template> | ||||
|   <Tabs defaultActiveKey="2" size="small"> | ||||
|     <TabPane tab="Tab 1" tabKey="1">Content of tab 1</TabPane> | ||||
|     <TabPane tab="Tab 2" tabKey="2">Content of tab 2</TabPane> | ||||
|     <TabPane tab="Tab 3" tabKey="3">Content of tab 3</TabPane> | ||||
|   </Tabs> | ||||
| </template> | ||||
| <script> | ||||
| import { Tabs } from 'antd' | ||||
| export default { | ||||
|   components: { | ||||
|     Tabs, | ||||
|     TabPane: Tabs.TabPane, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | @ -1,10 +1,10 @@ | |||
| <template> | ||||
|   <div style="width: 500px"> | ||||
|     <RadioGroup v-model="mode" :style="{ marginBottom: 8 }"> | ||||
|     <RadioGroup v-model="mode" :style="{ marginBottom: '8px' }"> | ||||
|       <RadioButton value="top">Horizontal</RadioButton> | ||||
|       <RadioButton value="left">Vertical</RadioButton> | ||||
|     </RadioGroup> | ||||
|     <Tabs defaultActiveKey="1" :tabPosition="mode" :style="{ height: '200px'}"> | ||||
|     <Tabs defaultActiveKey="1" :tabPosition="mode" :style="{ height: '200px'}" @prevClick="callback" @nextClick="callback"> | ||||
|       <TabPane tab="Tab 1" tabKey="1">Content of tab 1</TabPane> | ||||
|       <TabPane tab="Tab 2" tabKey="2">Content of tab 2</TabPane> | ||||
|       <TabPane tab="Tab 3" tabKey="3">Content of tab 3</TabPane> | ||||
|  | @ -29,6 +29,9 @@ export default { | |||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     callback (val) { | ||||
|       console.log(val) | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     Tabs, | ||||
|  |  | |||
|  | @ -1,10 +1,5 @@ | |||
| <script> | ||||
| import Tabs from './Tabs' | ||||
| // import TabPane from './TabPane' | ||||
| import ScrollableInkTabBar from './ScrollableInkTabBar' | ||||
| import TabBar from './TabBar' | ||||
| import TabContent from './TabContent' | ||||
| import Icon from '../icon' | ||||
| import isFlexSupported from '../_util/isFlexSupported' | ||||
| export default { | ||||
|   props: { | ||||
|  | @ -12,11 +7,9 @@ export default { | |||
|     activeKey: String, | ||||
|     defaultActiveKey: String, | ||||
|     hideAdd: { type: Boolean, default: false }, | ||||
|     onChange: { type: Function, default: () => {} }, | ||||
|     onTabClick: { type: Function, default: () => {} }, | ||||
|     onPrevClick: { type: Function, default: () => {} }, | ||||
|     onNextClick: { type: Function, default: () => {} }, | ||||
|     tabBarStyle: Object, | ||||
|     tabBarExtraContent: [String, Number, Function], | ||||
|     destroyInactiveTabPane: { type: Boolean, default: false }, | ||||
|     type: { | ||||
|       validator (value) { | ||||
|         return ['line', 'card', 'editable-card'].includes(value) | ||||
|  | @ -27,20 +20,20 @@ export default { | |||
|         return ['top', 'right', 'bottom', 'left'].includes(value) | ||||
|       }, | ||||
|     }, | ||||
|     onEdit: { type: Function, default: () => {} }, | ||||
|     size: { | ||||
|       validator (value) { | ||||
|         return ['default', 'small'].includes(value) | ||||
|       }, | ||||
|     }, | ||||
|     animated: Boolean | Object, | ||||
|     animated: { type: [Boolean, Object], default: undefined }, | ||||
|   }, | ||||
|   model: { | ||||
|     prop: 'activeKey', | ||||
|     event: 'change', | ||||
|   }, | ||||
|   methods: { | ||||
|     createNewTab (targetKey) { | ||||
|       const onEdit = this.$props.onEdit | ||||
|       if (onEdit) { | ||||
|         onEdit(targetKey, 'add') | ||||
|       } | ||||
|       this.$emit('edit', targetKey, 'add') | ||||
|     }, | ||||
| 
 | ||||
|     removeTab (targetKey, e) { | ||||
|  | @ -48,20 +41,21 @@ export default { | |||
|       if (!targetKey) { | ||||
|         return | ||||
|       } | ||||
| 
 | ||||
|       const onEdit = this.$props.onEdit | ||||
|       if (onEdit) { | ||||
|         onEdit(targetKey, 'remove') | ||||
|       } | ||||
|       this.$emit('edit', targetKey, 'remove') | ||||
|     }, | ||||
| 
 | ||||
|     handleChange (activeKey) { | ||||
|       // const onChange = this.$props.onChange | ||||
|       // if (onChange) { | ||||
|       //   onChange(activeKey) | ||||
|       // } | ||||
|       this.$emit('change', activeKey) | ||||
|     }, | ||||
|     onTabClick (val) { | ||||
|       this.$emit('tabClick', val) | ||||
|     }, | ||||
|     onPrevClick (val) { | ||||
|       this.$emit('prevClick', val) | ||||
|     }, | ||||
|     onNextClick (val) { | ||||
|       this.$emit('nextClick', val) | ||||
|     }, | ||||
|   }, | ||||
| 
 | ||||
|   mounted () { | ||||
|  | @ -72,29 +66,32 @@ export default { | |||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   render () { | ||||
|   render (createElement) { | ||||
|     const { | ||||
|       prefixCls, | ||||
|       size, | ||||
|       type = 'line', | ||||
|       tabPosition, | ||||
|       tabBarStyle, | ||||
|       // hideAdd, | ||||
|       hideAdd, | ||||
|       onTabClick, | ||||
|       onPrevClick, | ||||
|       onNextClick, | ||||
|       animated = true, | ||||
|     } = this.$props | ||||
|     let { tabBarExtraContent } = this.$props | ||||
|       animated, | ||||
|       destroyInactiveTabPane = false, | ||||
|       activeKey, | ||||
|       defaultActiveKey, | ||||
|     } = this | ||||
|     const { tabBarExtraContent } = this.$props | ||||
|     let { inkBarAnimated, tabPaneAnimated } = typeof animated === 'object' ? { // eslint-disable-line | ||||
|       inkBarAnimated: animated.inkBar, tabPaneAnimated: animated.tabPane, | ||||
|       inkBarAnimated: !!animated.inkBar, tabPaneAnimated: !!animated.tabPane, | ||||
|     } : { | ||||
|       inkBarAnimated: animated, tabPaneAnimated: animated, | ||||
|       inkBarAnimated: animated === undefined || animated, tabPaneAnimated: animated === undefined || animated, | ||||
|     } | ||||
| 
 | ||||
|     // card tabs should not have animation | ||||
|     if (type !== 'line') { | ||||
|       tabPaneAnimated = 'animated' in this.$props ? tabPaneAnimated : false | ||||
|       tabPaneAnimated = animated === undefined ? false : tabPaneAnimated | ||||
|     } | ||||
|     const cls = { | ||||
|       [`${prefixCls}-mini`]: size === 'small' || size, | ||||
|  | @ -103,56 +100,7 @@ export default { | |||
|       [`${prefixCls}-${type}`]: true, | ||||
|       [`${prefixCls}-no-animation`]: !tabPaneAnimated, | ||||
|     } | ||||
|     // only card type tabs can be added and closed | ||||
|     let childrenWithClose | ||||
|     // if (type === 'editable-card') { | ||||
|     //   childrenWithClose = [] | ||||
|     //   React.Children.forEach(children, (child, index) => { | ||||
|     //     let closable = child.props.closable | ||||
|     //     closable = typeof closable === 'undefined' ? true : closable | ||||
|     //     const closeIcon = closable ? ( | ||||
|     //       <Icon | ||||
|     //         type='close' | ||||
|     //         onClick={e => this.removeTab(child.key, e)} | ||||
|     //       /> | ||||
|     //     ) : null | ||||
|     //     childrenWithClose.push(cloneElement(child, { | ||||
|     //       tab: ( | ||||
|     //         <div className={closable ? undefined : `${prefixCls}-tab-unclosable`}> | ||||
|     //           {child.props.tab} | ||||
|     //           {closeIcon} | ||||
|     //         </div> | ||||
|     //       ), | ||||
|     //       key: child.key || index, | ||||
|     //     })) | ||||
|     //   }) | ||||
|     //   // Add new tab handler | ||||
|     //   if (!hideAdd) { | ||||
|     //     tabBarExtraContent = ( | ||||
|     //       <span> | ||||
|     //         <Icon type='plus' className={`${prefixCls}-new-tab`} onClick={this.createNewTab} /> | ||||
|     //         {tabBarExtraContent} | ||||
|     //       </span> | ||||
|     //     ) | ||||
|     //   } | ||||
|     // } | ||||
| 
 | ||||
|     tabBarExtraContent = tabBarExtraContent ? ( | ||||
|       <div class={`${prefixCls}-extra-content`}> | ||||
|         {tabBarExtraContent} | ||||
|       </div> | ||||
|     ) : null | ||||
| 
 | ||||
|     // const renderTabBar = () => ( | ||||
|     //   <ScrollableInkTabBar | ||||
|     //     inkBarAnimated={inkBarAnimated} | ||||
|     //     extraContent={tabBarExtraContent} | ||||
|     //     onTabClick={onTabClick} | ||||
|     //     onPrevClick={onPrevClick} | ||||
|     //     onNextClick={onNextClick} | ||||
|     //     style={tabBarStyle} | ||||
|     //   /> | ||||
|     // ) | ||||
|     const tabBarProps = { | ||||
|       inkBarAnimated, | ||||
|       extraContent: tabBarExtraContent, | ||||
|  | @ -160,21 +108,40 @@ export default { | |||
|       onPrevClick, | ||||
|       onNextClick, | ||||
|       style: tabBarStyle, | ||||
|       hideAdd, | ||||
|       removeTab: this.removeTab, | ||||
|       createNewTab: this.createNewTab, | ||||
|     } | ||||
|     const tabContentProps = { | ||||
|       animated: tabPaneAnimated, | ||||
|       animatedWithMargin: true, | ||||
|     } | ||||
|     const self = this | ||||
|     const tabsProps = { | ||||
|       props: { | ||||
|         prefixCls, | ||||
|         tabBarPosition: tabPosition, | ||||
|         onChange: this.handleChange, | ||||
|         tabBarProps: tabBarProps, | ||||
|         tabContentProps: tabContentProps, | ||||
|         destroyInactiveTabPane, | ||||
|         activeKey, | ||||
|         defaultActiveKey, | ||||
|         type, | ||||
|         onTabClick: this.onTabClick, | ||||
|       }, | ||||
|       on: { | ||||
|         change (val) { | ||||
|           self.handleChange(val) | ||||
|         }, | ||||
|       }, | ||||
|     } | ||||
|     return ( | ||||
|       <Tabs | ||||
|         {...this.$props} | ||||
|         class={cls} | ||||
|         tabBarPosition={tabPosition} | ||||
|         onChange={this.handleChange} | ||||
|         tabBarProps={tabBarProps} | ||||
|         tabContentProps={tabContentProps} | ||||
|         {...tabsProps} | ||||
|       > | ||||
|         {childrenWithClose || this.$slots.default} | ||||
|         {this.$slots.default} | ||||
|       </Tabs> | ||||
|     ) | ||||
|   }, | ||||
|  |  | |||
|  | @ -0,0 +1,52 @@ | |||
| --- | ||||
| category: Components | ||||
| subtitle: 标签页 | ||||
| type: Data Display | ||||
| title: Tabs | ||||
| cols: 1 | ||||
| --- | ||||
| 
 | ||||
| 选项卡切换组件。 | ||||
| 
 | ||||
| ## 何时使用 | ||||
| 
 | ||||
| 提供平级的区域将大块内容进行收纳和展现,保持界面整洁。 | ||||
| 
 | ||||
| Ant Design 依次提供了三级选项卡,分别用于不同的场景。 | ||||
| 
 | ||||
| - 卡片式的页签,提供可关闭的样式,常用于容器顶部。 | ||||
| - 标准线条式页签,用于容器内部的主功能切换,这是最常用的 Tabs。 | ||||
| - [RadioButton](/components/radio/#components-radio-demo-radiobutton) 可作为更次级的页签来使用。 | ||||
| 
 | ||||
| ## API | ||||
| 
 | ||||
| ### Tabs | ||||
| 
 | ||||
| | 参数 | 说明 | 类型 | 默认值 | | ||||
| | --- | --- | --- | --- | | ||||
| | activeKey | 当前激活 tab 面板的 key | string | 无 | | ||||
| | animated | 是否使用动画切换 Tabs,在 `tabPosition=top|bottom` 时有效 | boolean \| {inkBar:boolean, tabPane:boolean} | true, 当 type="card" 时为 false | | ||||
| | defaultActiveKey | 初始化选中面板的 key,如果没有设置 activeKey | string | 第一个面板 | | ||||
| | hideAdd | 是否隐藏加号图标,在 `type="editable-card"` 时有效 | boolean | false | | ||||
| | size | 大小,提供 `default` 和 `small` 两种大小,仅当 `type="line"` 时生效。 | string | 'default' | | ||||
| | tabBarExtraContent | tab bar 上额外的元素 | string\|number\|Function | 无 | | ||||
| | tabBarStyle | tab bar 的样式对象 | object | - | | ||||
| | tabPosition | 页签位置,可选值有 `top` `right` `bottom` `left` | string | 'top' | | ||||
| | type | 页签的基本样式,可选 `line`、`card` `editable-card` 类型 | string | 'line' | | ||||
| 
 | ||||
| 
 | ||||
| ### 事件 | ||||
| | 参数 | 说明 | 类型 | 默认值 | | ||||
| | change | 切换面板的回调 | Function | 无 | | ||||
| | edit | 新增和删除页签的回调,在 `type="editable-card"` 时有效 | (targetKey, action): void | 无 | | ||||
| | nextClick | next 按钮被点击的回调 | Function | 无 | | ||||
| | prevClick | prev 按钮被点击的回调 | Function | 无 | | ||||
| | tabClick | tab 被点击的回调 | Function | 无 | | ||||
| 
 | ||||
| ### Tabs.TabPane | ||||
| 
 | ||||
| | 参数 | 说明 | 类型 | 默认值 | | ||||
| | --- | --- | --- | --- | | ||||
| | forceRender | 被隐藏时是否渲染 DOM 结构 | boolean | false | | ||||
| | tabKey | 对应 activeKey | string | 无 | | ||||
| | tab | 选项卡头显示文字 | string\|Function | 无 | | ||||
		Loading…
	
		Reference in New Issue
	
	 tangjinzhou
						tangjinzhou