MultiTab.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <script>
  2. import events from './events'
  3. export default {
  4. name: 'MultiTab',
  5. data () {
  6. return {
  7. fullPathList: [],
  8. pages: [],
  9. activeKey: '',
  10. newTabIndex: 0
  11. }
  12. },
  13. created () {
  14. // bind event
  15. events.$on('open', val => {
  16. if (!val) {
  17. throw new Error(`multi-tab: open tab ${val} err`)
  18. }
  19. this.activeKey = val
  20. }).$on('close', val => {
  21. if (!val) {
  22. this.remove(this.activeKey)
  23. return
  24. }
  25. this.remove(val)
  26. })
  27. this.pages.push(this.$route)
  28. this.fullPathList.push(this.$route.fullPath)
  29. this.selectedLastPath()
  30. },
  31. methods: {
  32. onEdit (targetKey, action) {
  33. this[action](targetKey)
  34. },
  35. remove (targetKey) {
  36. this.pages = this.pages.filter(page => page.fullPath !== targetKey)
  37. this.fullPathList = this.fullPathList.filter(path => path !== targetKey)
  38. // 判断当前标签是否关闭,若关闭则跳转到最后一个还存在的标签页
  39. if (!this.fullPathList.includes(this.activeKey)) {
  40. this.selectedLastPath()
  41. }
  42. },
  43. selectedLastPath () {
  44. this.activeKey = this.fullPathList[this.fullPathList.length - 1]
  45. },
  46. // content menu
  47. closeThat (e) {
  48. // 判断是否为最后一个标签页,如果是最后一个,则无法被关闭
  49. if (this.fullPathList.length > 1) {
  50. this.remove(e)
  51. } else {
  52. this.$message.info('这是最后一个标签了, 无法被关闭')
  53. }
  54. },
  55. closeLeft (e) {
  56. const currentIndex = this.fullPathList.indexOf(e)
  57. if (currentIndex > 0) {
  58. this.fullPathList.forEach((item, index) => {
  59. if (index < currentIndex) {
  60. this.remove(item)
  61. }
  62. })
  63. } else {
  64. this.$message.info('左侧没有标签')
  65. }
  66. },
  67. closeRight (e) {
  68. const currentIndex = this.fullPathList.indexOf(e)
  69. if (currentIndex < (this.fullPathList.length - 1)) {
  70. this.fullPathList.forEach((item, index) => {
  71. if (index > currentIndex) {
  72. this.remove(item)
  73. }
  74. })
  75. } else {
  76. this.$message.info('右侧没有标签')
  77. }
  78. },
  79. closeAll (e) {
  80. const currentIndex = this.fullPathList.indexOf(e)
  81. this.fullPathList.forEach((item, index) => {
  82. if (index !== currentIndex) {
  83. this.remove(item)
  84. }
  85. })
  86. },
  87. closeMenuClick (key, route) {
  88. this[key](route)
  89. },
  90. renderTabPaneMenu (e) {
  91. return (
  92. <a-menu {...{ on: { click: ({ key, item, domEvent }) => { this.closeMenuClick(key, e) } } }}>
  93. <a-menu-item key="closeThat">关闭当前标签</a-menu-item>
  94. <a-menu-item key="closeRight">关闭右侧</a-menu-item>
  95. <a-menu-item key="closeLeft">关闭左侧</a-menu-item>
  96. <a-menu-item key="closeAll">关闭全部</a-menu-item>
  97. </a-menu>
  98. )
  99. },
  100. // render
  101. renderTabPane (title, keyPath) {
  102. const menu = this.renderTabPaneMenu(keyPath)
  103. return (
  104. <a-dropdown overlay={menu} trigger={['contextmenu']}>
  105. <span style={{ userSelect: 'none' }}>{ title }</span>
  106. </a-dropdown>
  107. )
  108. }
  109. },
  110. watch: {
  111. '$route': function (newVal) {
  112. this.activeKey = newVal.fullPath
  113. if (this.fullPathList.indexOf(newVal.fullPath) < 0) {
  114. this.fullPathList.push(newVal.fullPath)
  115. this.pages.push(newVal)
  116. }
  117. },
  118. activeKey: function (newPathKey) {
  119. this.$router.push({ path: newPathKey })
  120. }
  121. },
  122. render () {
  123. const { onEdit, $data: { pages } } = this
  124. const panes = pages.map(page => {
  125. return (
  126. <a-tab-pane
  127. style={{ height: 0 }}
  128. tab={this.renderTabPane(page.meta.title, page.fullPath)}
  129. key={page.fullPath} closable={pages.length > 1}
  130. >
  131. </a-tab-pane>)
  132. })
  133. return (
  134. <div class="ant-pro-multi-tab">
  135. <div class="ant-pro-multi-tab-wrapper">
  136. <a-tabs
  137. hideAdd
  138. type={'editable-card'}
  139. v-model={this.activeKey}
  140. tabBarStyle={{ background: '#FFF', margin: 0, paddingLeft: '16px', paddingTop: '1px' }}
  141. {...{ on: { edit: onEdit } }}>
  142. {panes}
  143. </a-tabs>
  144. </div>
  145. </div>
  146. )
  147. }
  148. }
  149. </script>