Browse Source

bug fix: tooltip和title指令没有考虑到目标元素被从DOM卸载的情况

任一存 2 years ago
parent
commit
44bb6b0658

+ 25 - 48
packages/qjkankan-editor/src/directives/vTitleInEditor.js

@@ -1,9 +1,20 @@
 import Vue from 'vue'
 
 let timerId = null
+let intervalId = null
 let isShowTitle = false
 let titleNode = null
 
+function removeTitle() {
+  if (!isShowTitle) {
+    clearTimeout(timerId)
+  } else {
+    isShowTitle = false
+    document.body.removeChild(titleNode)
+    clearInterval(intervalId)
+  }
+}
+
 Vue.directive('title', {
   bind: function (el, binding) {
     if (!binding.value) {
@@ -37,58 +48,24 @@ Vue.directive('title', {
           if (e.clientY + 18 + titleNode.offsetHeight > document.documentElement.clientHeight) {
             titleNode.style.top = document.documentElement.clientHeight - titleNode.offsetHeight + 'px'
           }
+
+          intervalId = setInterval(() => {
+            if (!document.contains(el)) {
+              removeTitle()
+            }
+          }, 300);
+          
         }, 500);
       }
     }, {
       passive: false,
     })
-    el.addEventListener('mouseleave', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('mousedown', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('keydown', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('scroll', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('dragover', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('dragleave', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
+
+    el.addEventListener('mouseleave', removeTitle)
+    el.addEventListener('mousedown', removeTitle)
+    el.addEventListener('keydown', removeTitle)
+    el.addEventListener('scroll', removeTitle)
+    el.addEventListener('dragover', removeTitle)
+    el.addEventListener('dragleave', removeTitle)
   },
 })

+ 25 - 48
packages/qjkankan-editor/src/directives/vTitleInManageCenter.js

@@ -1,9 +1,20 @@
 import Vue from 'vue'
 
 let timerId = null
+let intervalId = null
 let isShowTitle = false
 let titleNode = null
 
+function removeTitle() {
+  if (!isShowTitle) {
+    clearTimeout(timerId)
+  } else {
+    isShowTitle = false
+    document.body.removeChild(titleNode)
+    clearInterval(intervalId)
+  }
+}
+
 Vue.directive('title', {
   bind: function (el, binding) {
     if (!binding.value) {
@@ -36,58 +47,24 @@ Vue.directive('title', {
           if (e.clientY + 18 + titleNode.offsetHeight > document.documentElement.clientHeight) {
             titleNode.style.top = document.documentElement.clientHeight - titleNode.offsetHeight + 'px'
           }
+
+          intervalId = setInterval(() => {
+            if (!document.contains(el)) {
+              removeTitle()
+            }
+          }, 300);
+          
         }, 500);
       }
     }, {
       passive: false,
     })
-    el.addEventListener('mouseleave', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('mousedown', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('keydown', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('scroll', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('dragover', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
-    el.addEventListener('dragleave', function () {
-      if (!isShowTitle) {
-        clearTimeout(timerId)
-      } else {
-        isShowTitle = false
-        document.body.removeChild(titleNode)
-      }
-    })
+
+    el.addEventListener('mouseleave', removeTitle)
+    el.addEventListener('mousedown', removeTitle)
+    el.addEventListener('keydown', removeTitle)
+    el.addEventListener('scroll', removeTitle)
+    el.addEventListener('dragover', removeTitle)
+    el.addEventListener('dragleave', removeTitle)
   },
 })

+ 28 - 51
packages/qjkankan-editor/src/directives/vTooltipInEditor.js

@@ -1,12 +1,23 @@
 import Vue from 'vue'
 import {computePosition, offset, flip, shift, arrow} from '@floating-ui/dom';
- 
+
+let tooltipNode = null
+let intervalId = null
+
+function removeTooltip() {
+  try {
+    clearInterval(intervalId)
+    document.body.removeChild(tooltipNode)
+  } catch(e) {
+    console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
+  }
+}
+
 Vue.directive('tooltip', {
   bind: function (el, binding) {
     if (!binding.value) {
       return
     }
-    let tooltipNode = null
     el.addEventListener('mouseenter', function(e) {
       tooltipNode = document.createElement('div')
       tooltipNode.style.position = 'fixed'
@@ -70,58 +81,24 @@ Vue.directive('tooltip', {
           left: arrowX != null ? `${arrowX}px` : '',
           [staticSide]: '-6px',
         });
+      }).catch((err) => {
+        console.log('计算tooltip位置时出现异常,可能因为目标元素已经被卸载。')
       });
+
+      intervalId = setInterval(() => {
+        if (!document.contains(el)) {
+          removeTooltip()
+        }
+      }, 300);
     }, {
       passive: false,
     })
-    el.addEventListener('mouseleave', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('mousedown', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('keydown', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('scroll', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('dragstart', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('dragstart', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('dragleave', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
+    el.addEventListener('mouseleave', removeTooltip)
+    el.addEventListener('mousedown', removeTooltip)
+    el.addEventListener('keydown', removeTooltip)
+    el.addEventListener('scroll', removeTooltip)
+    el.addEventListener('dragstart', removeTooltip)
+    el.addEventListener('dragstart', removeTooltip)
+    el.addEventListener('dragleave', removeTooltip)
   },
 })

+ 22 - 51
packages/qjkankan-editor/src/directives/vTooltipInManageCenter.js

@@ -1,12 +1,23 @@
 import Vue from 'vue'
 import {computePosition, offset, flip, shift, arrow} from '@floating-ui/dom';
- 
+
+let tooltipNode = null
+let intervalId = null
+
+function removeTooltip() {
+  try {
+    clearInterval(intervalId)
+    document.body.removeChild(tooltipNode)
+  } catch(e) {
+    console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
+  }
+}
+
 Vue.directive('tooltip', {
   bind: function (el, binding) {
     if (!binding.value) {
       return
     }
-    let tooltipNode = null
     el.addEventListener('mouseenter', function(e) {
       tooltipNode = document.createElement('div')
       tooltipNode.style.position = 'fixed'
@@ -70,58 +81,18 @@ Vue.directive('tooltip', {
           left: arrowX != null ? `${arrowX}px` : '',
           [staticSide]: '-6px',
         });
+      }).catch((err) => {
+        console.log('计算tooltip位置时出现异常,可能因为目标元素已经被卸载。')
       });
     }, {
       passive: false,
     })
-    el.addEventListener('mouseleave', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('mousedown', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('keydown', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('scroll', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('dragstart', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('dragstart', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
-    el.addEventListener('dragleave', function () {
-      try {
-        document.body.removeChild(tooltipNode)
-      } catch(e) {
-        console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
-      }
-    })
+    el.addEventListener('mouseleave', removeTooltip)
+    el.addEventListener('mousedown', removeTooltip)
+    el.addEventListener('keydown', removeTooltip)
+    el.addEventListener('scroll', removeTooltip)
+    el.addEventListener('dragstart', removeTooltip)
+    el.addEventListener('dragstart', removeTooltip)
+    el.addEventListener('dragleave', removeTooltip)
   },
 })