overlay-manager.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import Vue from "vue";
  2. import overlayComponent from "./overlay.vue";
  3. let modalStack = [];
  4. let _zIndex = 2000;
  5. let overlay;
  6. const overlayManager = {
  7. lockCount: 0,
  8. get zIndex() {
  9. return ++_zIndex;
  10. },
  11. get topStack() {
  12. return modalStack[modalStack.length - 1];
  13. },
  14. updateOverlay() {
  15. const { clickHandle, topStack } = overlayManager;
  16. if (!overlay) {
  17. overlay = mount(overlayComponent, {
  18. nativeOn: {
  19. click: clickHandle,
  20. },
  21. });
  22. }
  23. if (topStack) {
  24. const { vm, config } = topStack;
  25. const el = vm.$el;
  26. el && el.parentNode && el.parentNode.nodeType !== 11
  27. ? el.parentNode.appendChild(overlay.$el)
  28. : document.body.appendChild(overlay.$el);
  29. Object.assign(overlay, config, {
  30. value: true,
  31. });
  32. } else {
  33. overlay.value = false;
  34. }
  35. },
  36. //打开遮罩层
  37. openModal(vm, config) {
  38. let { zIndex, duration, overlayClass, overlayStyle} = config;
  39. modalStack.push({
  40. vm,
  41. config: {
  42. zIndex,
  43. duration,
  44. overlayClass,
  45. overlayStyle,
  46. },
  47. });
  48. overlayManager.updateOverlay();
  49. },
  50. clickHandle() {
  51. const { topStack } = overlayManager;
  52. //防止多次点击
  53. if (modalStack.length && topStack.vm.closeOnClickOverlay) {
  54. topStack.vm.$emit("click-overlay");
  55. topStack.vm.close();
  56. }
  57. },
  58. closeOverlay(vm) {
  59. if (modalStack.length) {
  60. if (overlayManager.topStack.vm === vm) {
  61. modalStack.pop();
  62. overlayManager.updateOverlay();
  63. } else {
  64. modalStack = modalStack.filter((item) => item.vm !== vm);
  65. }
  66. }
  67. },
  68. };
  69. const overlayProps = {
  70. value: {
  71. type: Boolean,
  72. default: false,
  73. },
  74. overlay: {
  75. type: Boolean,
  76. default: true,
  77. },
  78. lockScroll: {
  79. type: Boolean,
  80. default: true,
  81. },
  82. duration: {
  83. type: Number,
  84. default: 0.3,
  85. },
  86. closeOnClickOverlay: {
  87. type: Boolean,
  88. default: true,
  89. },
  90. overlayClass: {
  91. type: String,
  92. default: "",
  93. },
  94. overlayStyle: {
  95. type: Object,
  96. default: function () {
  97. return null
  98. },
  99. },
  100. zIndex: {
  101. type: Number
  102. },
  103. };
  104. function mount(Component, data) {
  105. const instance = new Vue({
  106. props: Component.props,
  107. render(h) {
  108. return h(Component, {
  109. props:this.$props,
  110. ...data,
  111. });
  112. },
  113. }).$mount();
  114. return instance;
  115. }
  116. function getProps(){
  117. if(!this)return {}
  118. let obj = {};
  119. Object.keys(overlayProps).forEach(res=>{
  120. obj[res] = this[res]
  121. })
  122. return obj
  123. }
  124. export {overlayManager ,overlayProps, getProps};