1 |
|
2 |
|
3 | import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
|
4 | import scrollbarWidth from 'element-ui/src/utils/scrollbar-width';
|
5 | import { toObject } from 'element-ui/src/utils/util';
|
6 | import Bar from './bar';
|
7 |
|
8 |
|
9 | export 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,
|
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 | };
|