Commit 297648f1e634900ce4e22498f9c061f670c7321f

Authored by 梁灏
1 parent 300bd662

fixed #1063

examples/routers/spin.vue
@@ -181,6 +181,8 @@ @@ -181,6 +181,8 @@
181 </div> 181 </div>
182 <br> 182 <br>
183 切换显示状态:<i-switch @on-change="spinShow = !spinShow"></i-switch> 183 切换显示状态:<i-switch @on-change="spinShow = !spinShow"></i-switch>
  184 + <Button @click="show">show</Button>
  185 + <Button @click="hide">hide</Button>
184 </div> 186 </div>
185 </template> 187 </template>
186 <script> 188 <script>
@@ -189,6 +191,29 @@ @@ -189,6 +191,29 @@
189 return { 191 return {
190 spinShow: true 192 spinShow: true
191 } 193 }
  194 + },
  195 + methods: {
  196 + show () {
  197 + this.$Spin.show({
  198 + render: (h) => {
  199 + return h('div', [
  200 + h('Icon', {
  201 + props: {
  202 + type: 'load-c',
  203 + size: 24
  204 + }
  205 + }),
  206 + h('div', 'Loading')
  207 + ])
  208 + }
  209 + });
  210 + setTimeout(() => {
  211 + this.$Spin.hide();
  212 + }, 3000)
  213 + },
  214 + hide () {
  215 + this.$Spin.hide();
  216 + }
192 } 217 }
193 } 218 }
194 </script> 219 </script>
src/components/modal/mixins-scrollbar.js 0 → 100644
  1 +// used for Modal & $Spin
  2 +import { getScrollBarSize } from '../../utils/assist';
  3 +export default {
  4 + methods: {
  5 + checkScrollBar () {
  6 + let fullWindowWidth = window.innerWidth;
  7 + if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
  8 + const documentElementRect = document.documentElement.getBoundingClientRect();
  9 + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
  10 + }
  11 + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
  12 + if (this.bodyIsOverflowing) {
  13 + this.scrollBarWidth = getScrollBarSize();
  14 + }
  15 + },
  16 + setScrollBar () {
  17 + if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {
  18 + document.body.style.paddingRight = `${this.scrollBarWidth}px`;
  19 + }
  20 + },
  21 + resetScrollBar () {
  22 + document.body.style.paddingRight = '';
  23 + },
  24 + addScrollEffect () {
  25 + this.checkScrollBar();
  26 + this.setScrollBar();
  27 + document.body.style.overflow = 'hidden';
  28 + },
  29 + removeScrollEffect() {
  30 + document.body.style.overflow = '';
  31 + this.resetScrollBar();
  32 + }
  33 + }
  34 +};
0 \ No newline at end of file 35 \ No newline at end of file
src/components/modal/modal.vue
@@ -30,15 +30,15 @@ @@ -30,15 +30,15 @@
30 import Icon from '../icon'; 30 import Icon from '../icon';
31 import iButton from '../button/button.vue'; 31 import iButton from '../button/button.vue';
32 import TransferDom from '../../directives/transfer-dom'; 32 import TransferDom from '../../directives/transfer-dom';
33 - import { getScrollBarSize } from '../../utils/assist';  
34 import Locale from '../../mixins/locale'; 33 import Locale from '../../mixins/locale';
35 import Emitter from '../../mixins/emitter'; 34 import Emitter from '../../mixins/emitter';
  35 + import ScrollbarMixins from './mixins-scrollbar';
36 36
37 const prefixCls = 'ivu-modal'; 37 const prefixCls = 'ivu-modal';
38 38
39 export default { 39 export default {
40 name: 'Modal', 40 name: 'Modal',
41 - mixins: [ Locale, Emitter ], 41 + mixins: [ Locale, Emitter, ScrollbarMixins ],
42 components: { Icon, iButton }, 42 components: { Icon, iButton },
43 directives: { TransferDom }, 43 directives: { TransferDom },
44 props: { 44 props: {
@@ -186,34 +186,6 @@ @@ -186,34 +186,6 @@
186 } 186 }
187 } 187 }
188 }, 188 },
189 - checkScrollBar () {  
190 - let fullWindowWidth = window.innerWidth;  
191 - if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8  
192 - const documentElementRect = document.documentElement.getBoundingClientRect();  
193 - fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);  
194 - }  
195 - this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;  
196 - if (this.bodyIsOverflowing) {  
197 - this.scrollBarWidth = getScrollBarSize();  
198 - }  
199 - },  
200 - setScrollBar () {  
201 - if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {  
202 - document.body.style.paddingRight = `${this.scrollBarWidth}px`;  
203 - }  
204 - },  
205 - resetScrollBar () {  
206 - document.body.style.paddingRight = '';  
207 - },  
208 - addScrollEffect () {  
209 - this.checkScrollBar();  
210 - this.setScrollBar();  
211 - document.body.style.overflow = 'hidden';  
212 - },  
213 - removeScrollEffect() {  
214 - document.body.style.overflow = '';  
215 - this.resetScrollBar();  
216 - },  
217 animationFinish() { 189 animationFinish() {
218 this.$emit('on-hidden'); 190 this.$emit('on-hidden');
219 } 191 }
src/components/spin/index.js
1 -import Spin from './spin.vue'; 1 +import Spin from './spin.js';
  2 +
  3 +let spinInstance;
  4 +
  5 +function getSpinInstance (render = undefined) {
  6 + spinInstance = spinInstance || Spin.newInstance({
  7 + render: render
  8 + });
  9 +
  10 + return spinInstance;
  11 +}
  12 +
  13 +function loading (options) {
  14 + const render = ('render' in options) ? options.render : undefined;
  15 + let instance = getSpinInstance(render);
  16 +
  17 + instance.show(options);
  18 +}
  19 +
  20 +Spin.show = function (props = {}) {
  21 + return loading(props);
  22 +};
  23 +Spin.hide = function () {
  24 + if (!spinInstance) return false;
  25 +
  26 + const instance = getSpinInstance();
  27 +
  28 + instance.remove(() => {
  29 + spinInstance = null;
  30 + });
  31 +};
  32 +
2 export default Spin; 33 export default Spin;
3 \ No newline at end of file 34 \ No newline at end of file
src/components/spin/spin.js 0 → 100644
  1 +import Vue from 'vue';
  2 +import Spin from './spin.vue';
  3 +
  4 +Spin.newInstance = properties => {
  5 + const _props = properties || {};
  6 +
  7 + const Instance = new Vue({
  8 + data: Object.assign({}, _props, {
  9 +
  10 + }),
  11 + render (h) {
  12 + let vnode = '';
  13 + if (this.render) {
  14 + vnode = h(Spin, {
  15 + props: {
  16 + fix: true,
  17 + fullscreen: true
  18 + }
  19 + }, [this.render(h)]);
  20 + } else {
  21 + vnode = h(Spin, {
  22 + props: {
  23 + size: 'large',
  24 + fix: true,
  25 + fullscreen: true
  26 + }
  27 + });
  28 + }
  29 + return h('div', {
  30 + 'class': 'ivu-spin-fullscreen'
  31 + }, [vnode]);
  32 + }
  33 + });
  34 +
  35 + const component = Instance.$mount();
  36 + document.body.appendChild(component.$el);
  37 + const spin = Instance.$children[0];
  38 +
  39 + return {
  40 + show () {
  41 + spin.visible = true;
  42 + },
  43 + remove (cb) {
  44 + spin.visible = false;
  45 + setTimeout(function() {
  46 + spin.$parent.$destroy();
  47 + document.body.removeChild(document.getElementsByClassName('ivu-spin-fullscreen')[0]);
  48 + cb();
  49 + }, 500);
  50 + },
  51 + component: spin
  52 + };
  53 +};
  54 +
  55 +export default Spin;
0 \ No newline at end of file 56 \ No newline at end of file
src/components/spin/spin.vue
1 <template> 1 <template>
2 <transition name="fade"> 2 <transition name="fade">
3 - <div :class="classes"> 3 + <div :class="classes" v-if="fullscreenVisible">
4 <div :class="mainClasses"> 4 <div :class="mainClasses">
5 <span :class="dotClasses"></span> 5 <span :class="dotClasses"></span>
6 <div :class="textClasses"><slot></slot></div> 6 <div :class="textClasses"><slot></slot></div>
@@ -10,11 +10,13 @@ @@ -10,11 +10,13 @@
10 </template> 10 </template>
11 <script> 11 <script>
12 import { oneOf } from '../../utils/assist'; 12 import { oneOf } from '../../utils/assist';
  13 + import ScrollbarMixins from '../modal/mixins-scrollbar';
13 14
14 const prefixCls = 'ivu-spin'; 15 const prefixCls = 'ivu-spin';
15 16
16 export default { 17 export default {
17 name: 'Spin', 18 name: 'Spin',
  19 + mixins: [ ScrollbarMixins ],
18 props: { 20 props: {
19 size: { 21 size: {
20 validator (value) { 22 validator (value) {
@@ -24,11 +26,17 @@ @@ -24,11 +26,17 @@
24 fix: { 26 fix: {
25 type: Boolean, 27 type: Boolean,
26 default: false 28 default: false
  29 + },
  30 + fullscreen: {
  31 + type: Boolean,
  32 + default: false
27 } 33 }
28 }, 34 },
29 data () { 35 data () {
30 return { 36 return {
31 - showText: false 37 + showText: false,
  38 + // used for $Spin
  39 + visible: false
32 }; 40 };
33 }, 41 },
34 computed: { 42 computed: {
@@ -39,6 +47,7 @@ @@ -39,6 +47,7 @@
39 [`${prefixCls}-${this.size}`]: !!this.size, 47 [`${prefixCls}-${this.size}`]: !!this.size,
40 [`${prefixCls}-fix`]: this.fix, 48 [`${prefixCls}-fix`]: this.fix,
41 [`${prefixCls}-show-text`]: this.showText, 49 [`${prefixCls}-show-text`]: this.showText,
  50 + [`${prefixCls}-fullscreen`]: this.fullscreen
42 } 51 }
43 ]; 52 ];
44 }, 53 },
@@ -50,6 +59,22 @@ @@ -50,6 +59,22 @@
50 }, 59 },
51 textClasses () { 60 textClasses () {
52 return `${prefixCls}-text`; 61 return `${prefixCls}-text`;
  62 + },
  63 + fullscreenVisible () {
  64 + if (this.fullscreen) {
  65 + return this.visible;
  66 + } else {
  67 + return true;
  68 + }
  69 + }
  70 + },
  71 + watch: {
  72 + visible (val) {
  73 + if (val) {
  74 + this.addScrollEffect();
  75 + } else {
  76 + this.removeScrollEffect();
  77 + }
53 } 78 }
54 }, 79 },
55 mounted () { 80 mounted () {
@@ -139,6 +139,7 @@ const install = function (Vue, opts = {}) { @@ -139,6 +139,7 @@ const install = function (Vue, opts = {}) {
139 Vue.prototype.$Message = Message; 139 Vue.prototype.$Message = Message;
140 Vue.prototype.$Modal = Modal; 140 Vue.prototype.$Modal = Modal;
141 Vue.prototype.$Notice = Notice; 141 Vue.prototype.$Notice = Notice;
  142 + Vue.prototype.$Spin = Spin;
142 }; 143 };
143 144
144 // auto install 145 // auto install
src/styles/components/spin.less
@@ -33,6 +33,9 @@ @@ -33,6 +33,9 @@
33 .square(100%); 33 .square(100%);
34 background-color: rgba(255,255,255,.9); 34 background-color: rgba(255,255,255,.9);
35 } 35 }
  36 + &-fullscreen{
  37 + z-index: @zindex-spin-fullscreen;
  38 + }
36 39
37 &-fix &-main { 40 &-fix &-main {
38 position: absolute; 41 position: absolute;
src/styles/custom.less
@@ -149,6 +149,7 @@ @@ -149,6 +149,7 @@
149 @zindex-tooltip : 1060; 149 @zindex-tooltip : 1060;
150 @zindex-transfer : 1060; 150 @zindex-transfer : 1060;
151 @zindex-loading-bar : 2000; 151 @zindex-loading-bar : 2000;
  152 +@zindex-spin-fullscreen : 2010;
152 153
153 // Animation 154 // Animation
154 @animation-time : .3s; 155 @animation-time : .3s;