MultiTab.vue 4.5 KB

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