aa2913ba2e1daccfc1b274c543e226e6634be5215c4f7a89cbc1e316b5197682aa9e0100f902ca4c9f357bac8cc1ad041e8e6176c0c26678297affa6f72ef5 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // reference https://github.com/noeldelgado/gemini-scrollbar/blob/master/index.js
  2. import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
  3. import scrollbarWidth from 'element-ui/src/utils/scrollbar-width';
  4. import { toObject } from 'element-ui/src/utils/util';
  5. import Bar from './bar';
  6. /* istanbul ignore next */
  7. export default {
  8. name: 'ElScrollbar',
  9. components: { Bar },
  10. props: {
  11. native: Boolean,
  12. wrapStyle: {},
  13. wrapClass: {},
  14. viewClass: {},
  15. viewStyle: {},
  16. noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
  17. tag: {
  18. type: String,
  19. default: 'div'
  20. }
  21. },
  22. data() {
  23. return {
  24. sizeWidth: '0',
  25. sizeHeight: '0',
  26. moveX: 0,
  27. moveY: 0
  28. };
  29. },
  30. computed: {
  31. wrap() {
  32. return this.$refs.wrap;
  33. }
  34. },
  35. render(h) {
  36. let gutter = scrollbarWidth();
  37. let style = this.wrapStyle;
  38. if (gutter) {
  39. const gutterWith = `-${gutter}px`;
  40. const gutterStyle = `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`;
  41. if (Array.isArray(this.wrapStyle)) {
  42. style = toObject(this.wrapStyle);
  43. style.marginRight = style.marginBottom = gutterWith;
  44. } else if (typeof this.wrapStyle === 'string') {
  45. style += gutterStyle;
  46. } else {
  47. style = gutterStyle;
  48. }
  49. }
  50. const view = h(this.tag, {
  51. class: ['el-scrollbar__view', this.viewClass],
  52. style: this.viewStyle,
  53. ref: 'resize'
  54. }, this.$slots.default);
  55. const wrap = (
  56. <div
  57. ref="wrap"
  58. style={ style }
  59. onScroll={ this.handleScroll }
  60. class={ [this.wrapClass, 'el-scrollbar__wrap', gutter ? '' : 'el-scrollbar__wrap--hidden-default'] }>
  61. { [view] }
  62. </div>
  63. );
  64. let nodes;
  65. if (!this.native) {
  66. nodes = ([
  67. wrap,
  68. <Bar
  69. move={ this.moveX }
  70. size={ this.sizeWidth }></Bar>,
  71. <Bar
  72. vertical
  73. move={ this.moveY }
  74. size={ this.sizeHeight }></Bar>
  75. ]);
  76. } else {
  77. nodes = ([
  78. <div
  79. ref="wrap"
  80. class={ [this.wrapClass, 'el-scrollbar__wrap'] }
  81. style={ style }>
  82. { [view] }
  83. </div>
  84. ]);
  85. }
  86. return h('div', { class: 'el-scrollbar' }, nodes);
  87. },
  88. methods: {
  89. handleScroll() {
  90. const wrap = this.wrap;
  91. this.moveY = ((wrap.scrollTop * 100) / wrap.clientHeight);
  92. this.moveX = ((wrap.scrollLeft * 100) / wrap.clientWidth);
  93. },
  94. update() {
  95. let heightPercentage, widthPercentage;
  96. const wrap = this.wrap;
  97. if (!wrap) return;
  98. heightPercentage = (wrap.clientHeight * 100 / wrap.scrollHeight);
  99. widthPercentage = (wrap.clientWidth * 100 / wrap.scrollWidth);
  100. this.sizeHeight = (heightPercentage < 100) ? (heightPercentage + '%') : '';
  101. this.sizeWidth = (widthPercentage < 100) ? (widthPercentage + '%') : '';
  102. }
  103. },
  104. mounted() {
  105. if (this.native) return;
  106. this.$nextTick(this.update);
  107. !this.noresize && addResizeListener(this.$refs.resize, this.update);
  108. },
  109. beforeDestroy() {
  110. if (this.native) return;
  111. !this.noresize && removeResizeListener(this.$refs.resize, this.update);
  112. }
  113. };