| <template> | 
|   <el-scrollbar | 
|     ref="scrollContainer" | 
|     :vertical="false" | 
|     class="scroll-container" | 
|     @wheel.native.prevent="handleScroll" | 
|   > | 
|     <slot /> | 
|   </el-scrollbar> | 
| </template> | 
|   | 
| <script> | 
| const tagAndTagSpacing = 4 // tagAndTagSpacing | 
|   | 
| export default { | 
|   name: 'ScrollPane', | 
|   data() { | 
|     return { | 
|       left: 0, | 
|     } | 
|   }, | 
|   computed: { | 
|     scrollWrapper() { | 
|       return this.$refs.scrollContainer.$refs.wrap | 
|     }, | 
|   }, | 
|   mounted() { | 
|     this.scrollWrapper.addEventListener('scroll', this.emitScroll, true) | 
|   }, | 
|   beforeDestroy() { | 
|     this.scrollWrapper.removeEventListener('scroll', this.emitScroll) | 
|   }, | 
|   methods: { | 
|     handleScroll(e) { | 
|       const eventDelta = e.wheelDelta || -e.deltaY * 40 | 
|       const $scrollWrapper = this.scrollWrapper | 
|       $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4 | 
|     }, | 
|     emitScroll() { | 
|       this.$emit('scroll') | 
|     }, | 
|     moveToTarget(currentTag, visitedViews) { | 
|       const $container = this.$refs.scrollContainer.$el | 
|       const $containerWidth = $container.offsetWidth | 
|       const $scrollWrapper = this.scrollWrapper | 
|       // 这边的tagList的顺序不能保证和实际源数组的顺序保持一致 | 
|       // 比如源数组中在某个位置删除一项,然后在相同位置加入一项,那么加入的这一项是在tagList末尾 | 
|       // 所以这边不能直接根据顺序去取第一项和最后一项 | 
|       const tagList = this.$parent.$refs.tag | 
|   | 
|       let firstTag = null | 
|       let lastTag = null | 
|   | 
|       // find first tag and last tag | 
|       if (tagList.length > 0) { | 
|         firstTag = tagList.find( | 
|           (item) => item?.to?.name === visitedViews[0].name | 
|         ) | 
|         lastTag = tagList.find( | 
|           (item) => | 
|             item?.to?.name === visitedViews[visitedViews.length - 1].name | 
|         ) | 
|       } | 
|   | 
|       if (firstTag === currentTag) { | 
|         $scrollWrapper.scrollLeft = 0 | 
|       } else if (lastTag === currentTag) { | 
|         $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth | 
|       } else { | 
|         // find preTag and nextTag | 
|         const currentIndex = visitedViews.findIndex( | 
|           (item) => item.name === currentTag?.to?.name | 
|         ) | 
|         const prevTag = tagList.find( | 
|           (item) => item?.to?.name === visitedViews[currentIndex - 1].name | 
|         ) | 
|         const nextTag = tagList.find( | 
|           (item) => item?.to?.name === visitedViews[currentIndex + 1].name | 
|         ) | 
|   | 
|         // the tag's offsetLeft after of nextTag | 
|         const afterNextTagOffsetLeft = | 
|           nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing | 
|   | 
|         // the tag's offsetLeft before of prevTag | 
|         const beforePrevTagOffsetLeft = | 
|           prevTag.$el.offsetLeft - tagAndTagSpacing | 
|   | 
|         if ( | 
|           afterNextTagOffsetLeft > | 
|           $scrollWrapper.scrollLeft + $containerWidth | 
|         ) { | 
|           $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth | 
|         } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) { | 
|           $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft | 
|         } | 
|       } | 
|     }, | 
|   }, | 
| } | 
| </script> | 
|   | 
| <style lang="scss" scoped> | 
| .scroll-container { | 
|   white-space: nowrap; | 
|   position: relative; | 
|   overflow: hidden; | 
|   width: 100%; | 
|   ::v-deep { | 
|     .el-scrollbar__bar { | 
|       bottom: 0px; | 
|     } | 
|     .el-scrollbar__wrap { | 
|       height: 49px; | 
|       overflow-x: auto !important; | 
|     } | 
|   } | 
| } | 
| </style> |