Commit 8f2d04a3 by wusiyi

fix: 尝试修复图片预览会留存的问题

parent 735473e1
......@@ -4,6 +4,7 @@ import {
RouteLocationNormalized,
NavigationGuardNext,
} from 'vue-router'
import { cleanupImagePreview } from '@/utils/hooks/useImagePreview.'
import Login from '@/views/Login.vue'
import Reset from '@/views/Reset.vue'
......@@ -341,6 +342,8 @@ router.beforeEach(
_from: RouteLocationNormalized,
next: NavigationGuardNext,
) => {
// 路由切换时清理图片预览,防止预览元素残留
cleanupImagePreview()
const token = getToken()
if (to.query.factoryCode) {
localStorage.setItem('factory_code', String(to.query.factoryCode))
......
import { ref } from 'vue'
import { ref, onUnmounted } from 'vue'
export default function useImagePreview() {
const show = ref(false)
const div = document.createElement('div')
div.style.position = 'fixed'
div.style.zIndex = '9999999999999'
div.style.display = 'none'
const img = document.createElement('img')
img.style.width = '300px'
div.appendChild(img)
document.body.appendChild(div)
// 单例模式:所有实例共享同一个预览元素
let previewDiv: HTMLDivElement | null = null
let previewImg: HTMLImageElement | null = null
const show = ref(false)
let currentTarget: HTMLElement | null = null
let mousemoveHandler: ((ev: MouseEvent) => void) | null = null
// 初始化预览元素(只创建一次)
function initPreviewElement() {
if (previewDiv) return
previewDiv = document.createElement('div')
previewDiv.style.position = 'fixed'
previewDiv.style.zIndex = '9999999999999'
previewDiv.style.display = 'none'
previewImg = document.createElement('img')
previewImg.style.width = '300px'
previewDiv.appendChild(previewImg)
document.body.appendChild(previewDiv)
}
// 清理函数:移除事件监听器和重置状态
function cleanup() {
if (mousemoveHandler) {
window.removeEventListener('mousemove', mousemoveHandler)
mousemoveHandler = null
}
if (previewDiv) {
previewDiv.style.display = 'none'
}
show.value = false
currentTarget = null
}
let currentTarget: HTMLElement | null = null
// 导出清理函数,供路由切换时使用
export function cleanupImagePreview() {
cleanup()
}
export default function useImagePreview() {
// 确保预览元素已初始化
initPreviewElement()
const mousemoveHandler = (ev: MouseEvent) => {
if (!currentTarget) return
// 创建 mousemove 处理器(如果还没有)
if (!mousemoveHandler) {
mousemoveHandler = (ev: MouseEvent) => {
if (!currentTarget || !previewDiv) {
cleanup()
return
}
const rect = currentTarget.getBoundingClientRect()
const inOrigin =
ev.clientX >= rect.left &&
......@@ -22,7 +57,7 @@ export default function useImagePreview() {
ev.clientY >= rect.top &&
ev.clientY <= rect.bottom
const divRect = div.getBoundingClientRect()
const divRect = previewDiv.getBoundingClientRect()
const inPreview =
ev.clientX >= divRect.left &&
ev.clientX <= divRect.right &&
......@@ -30,10 +65,8 @@ export default function useImagePreview() {
ev.clientY <= divRect.bottom
if (!inOrigin && !inPreview) {
div.style.display = 'none'
show.value = false
window.removeEventListener('mousemove', mousemoveHandler)
currentTarget = null
cleanup()
}
}
}
......@@ -44,12 +77,13 @@ export default function useImagePreview() {
newBorder?: boolean,
positionBOOTTOM?: boolean,
) => {
if (!previewDiv || !previewImg) return
ev.preventDefault()
if (show.value === true) return
img.src = url
img.style.backgroundColor = '#eee'
if (newBorder) img.style.border = '1px solid #eee'
if (newWitdh) img.style.width = newWitdh
previewImg.src = url
previewImg.style.backgroundColor = '#eee'
if (newBorder) previewImg.style.border = '1px solid #eee'
if (newWitdh) previewImg.style.width = newWitdh
const cW = document.body.clientWidth
const cH = document.body.clientHeight
const cX = ev.clientX
......@@ -59,14 +93,15 @@ export default function useImagePreview() {
else y = cY - 150
if (cX + 300 >= cW) x = cX - 300
else x = cX + 60
img.onload = () => {
div.style.left = x + 'px'
div.style.top = y + 'px'
div.style.display = 'block'
previewImg.onload = () => {
if (!previewDiv || !previewImg) return
previewDiv.style.left = x + 'px'
previewDiv.style.top = y + 'px'
previewDiv.style.display = 'block'
if (positionBOOTTOM) {
// 获取图片实际尺寸
const imgWidth = img.clientWidth
const imgHeight = img.clientHeight
const imgWidth = previewImg.clientWidth
const imgHeight = previewImg.clientHeight
// 计算新位置(鼠标正下方)
let x = cX / 2
......@@ -85,20 +120,26 @@ export default function useImagePreview() {
if (y < 0) {
y = 10
}
div.style.left = x + 'px'
div.style.top = y + 'px'
previewDiv.style.left = x + 'px'
previewDiv.style.top = y + 'px'
}
show.value = true
currentTarget = ev.currentTarget as HTMLElement
if (mousemoveHandler) {
window.addEventListener('mousemove', mousemoveHandler)
}
}
}
const mouseleaveImg = () => {
if (show.value === false) return
div.style.display = 'none'
show.value = false
// 在 mouseleave 时也要清理事件监听器
cleanup()
}
// 组件卸载时清理(防止内存泄漏)
onUnmounted(() => {
cleanup()
})
return { mouseoverImg, mouseleaveImg }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment