Ver Fonte

修复下拉框刷新后丢失层级,导致错误渲染到其他层级

cyy há 1 dia atrás
pai
commit
3e45f292b0

+ 1 - 1
src/business/platform/cat/dictionary/select.vue

@@ -1,5 +1,5 @@
 <template>
-  <ibps-tree-select
+    <ibps-tree-select
     v-if="treeData"
     v-model="selectData"
     :data="treeData"

+ 20 - 9
src/components/ibps-tree-select/dropdown.vue

@@ -1,6 +1,6 @@
 <template>
   <div
-    v-show="visible"
+    v-show="visible && ready"
     ref="root"
     class="el-tree-select-dropdown"
     :class="{ 'is-top': placement === 'top' }"
@@ -41,7 +41,8 @@ export default {
       left: 0,
       width: 0,
       maxHeight: DEFAULT_MAX_HEIGHT,
-      placement: 'bottom'
+      placement: 'bottom',
+      ready: false
     }
   },
   computed: {
@@ -70,10 +71,8 @@ export default {
   },
   watch: {
     visible(val) {
-      if (val) {
-        this.$nextTick(() => {
-          this.mountToBody()
-        })
+      if (!val) {
+        this.ready = false
       }
     }
   },
@@ -94,9 +93,18 @@ export default {
       }
     },
     updatePosition(referenceEl) {
-      if (!referenceEl || !this.visible) return
+      if (!referenceEl) return
+
+      // 每次打开重新取 z-index,避免刷新后提前挂载导致层级低于弹窗遮罩
+      this.zIndex = PopupManager.nextZIndex()
 
       const rect = referenceEl.getBoundingClientRect()
+      // 参考节点尚未布局(如弹窗刚打开)时暂不展示,等下次定位
+      if (rect.width === 0 && rect.height === 0) {
+        this.ready = false
+        return
+      }
+
       const viewportWidth = window.innerWidth
       const viewportHeight = window.innerHeight
 
@@ -106,13 +114,15 @@ export default {
 
       let left = rect.left
       if (left + width > viewportWidth - VIEWPORT_PADDING) {
-        left = Math.max(VIEWPORT_PADDING, viewportWidth - VIEWPORT_PADDING - width)
+        left = Math.max(
+          VIEWPORT_PADDING,
+          viewportWidth - VIEWPORT_PADDING - width
+        )
       }
       if (left < VIEWPORT_PADDING) {
         left = VIEWPORT_PADDING
       }
 
-      // 下方空间不足时翻转到上方
       const openToTop =
         spaceBelow < MIN_HEIGHT ||
         (spaceBelow < DEFAULT_MAX_HEIGHT && spaceAbove > spaceBelow)
@@ -138,6 +148,7 @@ export default {
       }
 
       this.mountToBody()
+      this.ready = true
     }
   }
 }

+ 3 - 0
src/components/ibps-tree-select/index.vue

@@ -332,6 +332,8 @@ export default {
   watch: {
     visible(val) {
       if (val) {
+        // 先同步定位并抬高 z-index,再绑定滚动/resize;避免提前显示在错误层级
+        this.syncDropdown()
         this.$nextTick(() => {
           this.syncDropdown()
           this.bindPositionEvents()
@@ -402,6 +404,7 @@ export default {
       const referenceEl = this.getReferenceEl()
       if (!dropdown || !referenceEl) return
       dropdown.updatePosition(referenceEl)
+      // clickoutside 依赖 popperElm;挂到 body 后需指向实际下拉节点
       this.popperElm = dropdown.$refs.root
     },
     bindPositionEvents() {