用 ref 实现图片点击放大预览的核心是通过 ref 精准获取 img 元素,读取其位置尺寸并动态渲染覆盖层;需在 onMounted 后操作 DOM,用 getBoundingClientRect 和 naturalWidth/naturalHeight 计算缩放参数,结合 transform 实现平滑动画,并在 onBeforeUnmount 中清理事件与引用。

用 ref 实现图片点击放大预览,核心是拿到原图 DOM 节点,读取其尺寸和位置,再动态渲染一个覆盖层显示放大效果。Vue 3 的 ref 非常适合做这件事——它能精准绑定单个元素,避免 querySelector 的不确定性。
一、用 ref 获取图片元素并监听点击
给 <img> 标签加 ref,在 setup 中定义响应式引用,并绑定 click 事件:
注意:ref 名要和模板中一致,且必须用 onMounted 确保 DOM 已挂载后再访问
- 在 script setup 中声明:
const imgRef = ref(null) - 模板中写:
<img ref="imgRef" @click="handleClick" :src="url" alt=""> - 点击时获取原图信息:
const rect = imgRef.value.getBoundingClientRect() - 保存
top、left、width、height,用于后续动画定位
二、用计算样式实现平滑缩放入场
放大图不能直接设为 100% 宽高——那样会失真或裁切。更稳妥的方式是:以原图中心为锚点,等比放大到视口宽度的 90%,同时保持宽高比。
- 根据
rect计算原图在视口中的中心坐标:centerX = rect.left + rect.width / 2 - 目标宽度设为
window.innerWidth * 0.9,高度按比例计算:targetHeight = targetWidth * (imgRef.value.naturalHeight / imgRef.value.naturalWidth) - 用
transform: scale() translate()做过渡动画,起点用原图位置+尺寸,终点居中+缩放
三、响应式适配不同屏幕与设备
移动端需禁用双指缩放干扰,桌面端可支持 Esc 关闭、鼠标滚轮缩放。关键点在于区分场景处理:
- 小屏幕(如手机):放大后禁止拖拽,点击关闭;添加
touch-action: none防止浏览器默认手势冲突 - 大屏幕:监听
keydown捕获 Esc 键;监听wheel事件,配合ctrlKey实现滚轮缩放 - 始终用
window.innerWidth / window.innerHeight动态计算最大显示区域,不写死像素值
四、收尾:安全销毁与内存管理
预览关闭后,记得清空 ref 引用、移除全局事件监听器,尤其避免在组件卸载后还尝试操作已销毁的 DOM。
- 使用
onBeforeUnmount清理keydown和wheel监听器 - 将预览状态(如
isPreviewOpen)设为false,触发 v-if 卸载子组件 - 避免在
imgRef.value上保留闭包引用,防止内存泄漏
不复杂但容易忽略细节:naturalWidth/naturalHeight 要等图片加载完成才能读取准确值,建议监听 imgRef.value.onload 或用 await imgRef.value.decode() 确保解码完成再计算尺寸。

















