tabs.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. import _mergeJSXProps from 'babel-helper-vue-jsx-merge-props';
  2. import _extends from 'babel-runtime/helpers/extends';
  3. import _defineProperty from 'babel-runtime/helpers/defineProperty';
  4. import _typeof from 'babel-runtime/helpers/typeof';
  5. import Icon from '../icon';
  6. import VcTabs, { TabPane } from '../vc-tabs/src';
  7. import TabContent from '../vc-tabs/src/TabContent';
  8. import { isFlexSupported } from '../_util/styleChecker';
  9. import PropTypes from '../_util/vue-types';
  10. import { getComponentFromProp, getOptionProps, filterEmpty, getListeners } from '../_util/props-util';
  11. import { cloneElement } from '../_util/vnode';
  12. import isValid from '../_util/isValid';
  13. import { ConfigConsumerProps } from '../config-provider/configConsumerProps';
  14. import TabBar from './TabBar';
  15. export default {
  16. TabPane: TabPane,
  17. name: 'ATabs',
  18. model: {
  19. prop: 'activeKey',
  20. event: 'change'
  21. },
  22. props: {
  23. prefixCls: PropTypes.string,
  24. activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  25. defaultActiveKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  26. hideAdd: PropTypes.bool.def(false),
  27. tabBarStyle: PropTypes.object,
  28. tabBarExtraContent: PropTypes.any,
  29. destroyInactiveTabPane: PropTypes.bool.def(false),
  30. type: PropTypes.oneOf(['line', 'card', 'editable-card']),
  31. tabPosition: PropTypes.oneOf(['top', 'right', 'bottom', 'left']).def('top'),
  32. size: PropTypes.oneOf(['default', 'small', 'large']),
  33. animated: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
  34. tabBarGutter: PropTypes.number,
  35. renderTabBar: PropTypes.func
  36. },
  37. inject: {
  38. configProvider: { 'default': function _default() {
  39. return ConfigConsumerProps;
  40. } }
  41. },
  42. mounted: function mounted() {
  43. var NO_FLEX = ' no-flex';
  44. var tabNode = this.$el;
  45. if (tabNode && !isFlexSupported && tabNode.className.indexOf(NO_FLEX) === -1) {
  46. tabNode.className += NO_FLEX;
  47. }
  48. },
  49. methods: {
  50. removeTab: function removeTab(targetKey, e) {
  51. e.stopPropagation();
  52. if (isValid(targetKey)) {
  53. this.$emit('edit', targetKey, 'remove');
  54. }
  55. },
  56. handleChange: function handleChange(activeKey) {
  57. this.$emit('change', activeKey);
  58. },
  59. createNewTab: function createNewTab(targetKey) {
  60. this.$emit('edit', targetKey, 'add');
  61. },
  62. onTabClick: function onTabClick(val) {
  63. this.$emit('tabClick', val);
  64. },
  65. onPrevClick: function onPrevClick(val) {
  66. this.$emit('prevClick', val);
  67. },
  68. onNextClick: function onNextClick(val) {
  69. this.$emit('nextClick', val);
  70. }
  71. },
  72. render: function render() {
  73. var _cls,
  74. _this = this,
  75. _contentCls;
  76. var h = arguments[0];
  77. var props = getOptionProps(this);
  78. var customizePrefixCls = props.prefixCls,
  79. size = props.size,
  80. _props$type = props.type,
  81. type = _props$type === undefined ? 'line' : _props$type,
  82. tabPosition = props.tabPosition,
  83. _props$animated = props.animated,
  84. animated = _props$animated === undefined ? true : _props$animated,
  85. hideAdd = props.hideAdd,
  86. renderTabBar = props.renderTabBar;
  87. var getPrefixCls = this.configProvider.getPrefixCls;
  88. var prefixCls = getPrefixCls('tabs', customizePrefixCls);
  89. var children = filterEmpty(this.$slots['default']);
  90. var tabBarExtraContent = getComponentFromProp(this, 'tabBarExtraContent');
  91. var tabPaneAnimated = (typeof animated === 'undefined' ? 'undefined' : _typeof(animated)) === 'object' ? animated.tabPane : animated;
  92. // card tabs should not have animation
  93. if (type !== 'line') {
  94. tabPaneAnimated = 'animated' in props ? tabPaneAnimated : false;
  95. }
  96. var cls = (_cls = {}, _defineProperty(_cls, prefixCls + '-vertical', tabPosition === 'left' || tabPosition === 'right'), _defineProperty(_cls, prefixCls + '-' + size, !!size), _defineProperty(_cls, prefixCls + '-card', type.indexOf('card') >= 0), _defineProperty(_cls, prefixCls + '-' + type, true), _defineProperty(_cls, prefixCls + '-no-animation', !tabPaneAnimated), _cls);
  97. // only card type tabs can be added and closed
  98. var childrenWithClose = [];
  99. if (type === 'editable-card') {
  100. childrenWithClose = [];
  101. children.forEach(function (child, index) {
  102. var props = getOptionProps(child);
  103. var closable = props.closable;
  104. closable = typeof closable === 'undefined' ? true : closable;
  105. var closeIcon = closable ? h(Icon, {
  106. attrs: {
  107. type: 'close'
  108. },
  109. 'class': prefixCls + '-close-x',
  110. on: {
  111. 'click': function click(e) {
  112. return _this.removeTab(child.key, e);
  113. }
  114. }
  115. }) : null;
  116. childrenWithClose.push(cloneElement(child, {
  117. props: {
  118. tab: h(
  119. 'div',
  120. { 'class': closable ? undefined : prefixCls + '-tab-unclosable' },
  121. [getComponentFromProp(child, 'tab'), closeIcon]
  122. )
  123. },
  124. key: child.key || index
  125. }));
  126. });
  127. // Add new tab handler
  128. if (!hideAdd) {
  129. tabBarExtraContent = h('span', [h(Icon, {
  130. attrs: { type: 'plus' },
  131. 'class': prefixCls + '-new-tab', on: {
  132. 'click': this.createNewTab
  133. }
  134. }), tabBarExtraContent]);
  135. }
  136. }
  137. tabBarExtraContent = tabBarExtraContent ? h(
  138. 'div',
  139. { 'class': prefixCls + '-extra-content' },
  140. [tabBarExtraContent]
  141. ) : null;
  142. var renderTabBarSlot = renderTabBar || this.$scopedSlots.renderTabBar;
  143. var listeners = getListeners(this);
  144. var tabBarProps = {
  145. props: _extends({}, this.$props, {
  146. prefixCls: prefixCls,
  147. tabBarExtraContent: tabBarExtraContent,
  148. renderTabBar: renderTabBarSlot
  149. }),
  150. on: listeners
  151. };
  152. var contentCls = (_contentCls = {}, _defineProperty(_contentCls, prefixCls + '-' + tabPosition + '-content', true), _defineProperty(_contentCls, prefixCls + '-card-content', type.indexOf('card') >= 0), _contentCls);
  153. var tabsProps = {
  154. props: _extends({}, getOptionProps(this), {
  155. prefixCls: prefixCls,
  156. tabBarPosition: tabPosition,
  157. // https://github.com/vueComponent/ant-design-vue/issues/2030
  158. // 如仅传递 tabBarProps 会导致,第二次执行 renderTabBar 时,丢失 on 属性,
  159. // 添加key之后,会在babel jsx 插件中做一次merge,最终TabBar接收的是一个新的对象,而不是 tabBarProps
  160. renderTabBar: function renderTabBar() {
  161. return h(TabBar, _mergeJSXProps([{ key: 'tabBar' }, tabBarProps]));
  162. },
  163. renderTabContent: function renderTabContent() {
  164. return h(TabContent, { 'class': contentCls, attrs: { animated: tabPaneAnimated, animatedWithMargin: true }
  165. });
  166. },
  167. children: childrenWithClose.length > 0 ? childrenWithClose : children,
  168. __propsSymbol__: Symbol()
  169. }),
  170. on: _extends({}, listeners, {
  171. change: this.handleChange
  172. }),
  173. 'class': cls
  174. };
  175. return h(VcTabs, tabsProps);
  176. }
  177. };