UNPKG

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