045a5e0aa7267a7eb411de7b75c450ae4cbde8c84b29b1ad21771ba037b79617ff83bce93fc39b7ec79f32ac0ad33ac66b2c8e76f15f31fa1300a2478ef6e4 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import Vue from 'vue';
  2. import loadingVue from './loading.vue';
  3. import { addClass, removeClass, getStyle } from 'element-ui/src/utils/dom';
  4. import { PopupManager } from 'element-ui/src/utils/popup';
  5. import afterLeave from 'element-ui/src/utils/after-leave';
  6. import merge from 'element-ui/src/utils/merge';
  7. const LoadingConstructor = Vue.extend(loadingVue);
  8. const defaults = {
  9. text: null,
  10. fullscreen: true,
  11. body: false,
  12. lock: false,
  13. customClass: ''
  14. };
  15. let fullscreenLoading;
  16. LoadingConstructor.prototype.originalPosition = '';
  17. LoadingConstructor.prototype.originalOverflow = '';
  18. LoadingConstructor.prototype.close = function() {
  19. if (this.fullscreen) {
  20. fullscreenLoading = undefined;
  21. }
  22. afterLeave(this, _ => {
  23. const target = this.fullscreen || this.body
  24. ? document.body
  25. : this.target;
  26. removeClass(target, 'el-loading-parent--relative');
  27. removeClass(target, 'el-loading-parent--hidden');
  28. if (this.$el && this.$el.parentNode) {
  29. this.$el.parentNode.removeChild(this.$el);
  30. }
  31. this.$destroy();
  32. }, 300);
  33. this.visible = false;
  34. };
  35. const addStyle = (options, parent, instance) => {
  36. let maskStyle = {};
  37. if (options.fullscreen) {
  38. instance.originalPosition = getStyle(document.body, 'position');
  39. instance.originalOverflow = getStyle(document.body, 'overflow');
  40. maskStyle.zIndex = PopupManager.nextZIndex();
  41. } else if (options.body) {
  42. instance.originalPosition = getStyle(document.body, 'position');
  43. ['top', 'left'].forEach(property => {
  44. let scroll = property === 'top' ? 'scrollTop' : 'scrollLeft';
  45. maskStyle[property] = options.target.getBoundingClientRect()[property] +
  46. document.body[scroll] +
  47. document.documentElement[scroll] +
  48. 'px';
  49. });
  50. ['height', 'width'].forEach(property => {
  51. maskStyle[property] = options.target.getBoundingClientRect()[property] + 'px';
  52. });
  53. } else {
  54. instance.originalPosition = getStyle(parent, 'position');
  55. }
  56. Object.keys(maskStyle).forEach(property => {
  57. instance.$el.style[property] = maskStyle[property];
  58. });
  59. };
  60. const Loading = (options = {}) => {
  61. if (Vue.prototype.$isServer) return;
  62. options = merge({}, defaults, options);
  63. if (typeof options.target === 'string') {
  64. options.target = document.querySelector(options.target);
  65. }
  66. options.target = options.target || document.body;
  67. if (options.target !== document.body) {
  68. options.fullscreen = false;
  69. } else {
  70. options.body = true;
  71. }
  72. if (options.fullscreen && fullscreenLoading) {
  73. return fullscreenLoading;
  74. }
  75. let parent = options.body ? document.body : options.target;
  76. let instance = new LoadingConstructor({
  77. el: document.createElement('div'),
  78. data: options
  79. });
  80. addStyle(options, parent, instance);
  81. if (instance.originalPosition !== 'absolute' && instance.originalPosition !== 'fixed' && instance.originalPosition !== 'sticky') {
  82. addClass(parent, 'el-loading-parent--relative');
  83. }
  84. if (options.fullscreen && options.lock) {
  85. addClass(parent, 'el-loading-parent--hidden');
  86. }
  87. parent.appendChild(instance.$el);
  88. Vue.nextTick(() => {
  89. instance.visible = true;
  90. });
  91. if (options.fullscreen) {
  92. fullscreenLoading = instance;
  93. }
  94. return instance;
  95. };
  96. export default Loading;