refactor(PdfViewer): 优化PDF查看器关闭逻辑和资源清理
添加PDF组件引用并实现销毁方法 延迟清理状态确保组件完成内部清理 新增onClose和onDestroy事件通知父组件
Showing
1 changed file
with
64 additions
and
16 deletions
| ... | @@ -11,14 +11,31 @@ | ... | @@ -11,14 +11,31 @@ |
| 11 | <div class="pdf-viewer-container"> | 11 | <div class="pdf-viewer-container"> |
| 12 | <!-- PDF内容区域 --> | 12 | <!-- PDF内容区域 --> |
| 13 | <div class="pdf-content" :class="{ 'pdf-no-select': preventSave }"> | 13 | <div class="pdf-content" :class="{ 'pdf-no-select': preventSave }"> |
| 14 | - <PDF v-if="url && show && !loadingError" :src="url" :showProgress="true" :progressColor="'#1989fa'" | 14 | + <PDF v-if="url && show && !loadingError" |
| 15 | - :showPageTooltip="true" :showBackToTopBtn="true" :scrollThreshold="300" | 15 | + ref="pdfRef" |
| 16 | + :src="url" | ||
| 17 | + :showProgress="true" | ||
| 18 | + :progressColor="'#1989fa'" | ||
| 19 | + :showPageTooltip="true" | ||
| 20 | + :showBackToTopBtn="true" | ||
| 21 | + :scrollThreshold="300" | ||
| 16 | :pdfWidth="`${Math.round(100 * zoomLevel)}%`" | 22 | :pdfWidth="`${Math.round(100 * zoomLevel)}%`" |
| 17 | - :rowGap="8" :page="1" :cMapUrl="'https://unpkg.com/pdfjs-dist@3.7.107/cmaps/'" | 23 | + :rowGap="8" |
| 18 | - :withCredentials="false" :useSystemFonts="true" :stopAtErrors="false" :disableFontFace="false" | 24 | + :page="1" |
| 19 | - :disableRange="false" :disableStream="false" :disableAutoFetch="false" @onProgress="handleProgress" | 25 | + :cMapUrl="'https://unpkg.com/pdfjs-dist@3.7.107/cmaps/'" |
| 20 | - @onComplete="handleComplete" @onScroll="handleScroll" @onPageChange="handlePageChange" | 26 | + :withCredentials="false" |
| 21 | - @onPdfInit="handlePdfInit" @onError="handlePdfError" /> | 27 | + :useSystemFonts="true" |
| 28 | + :stopAtErrors="false" | ||
| 29 | + :disableFontFace="false" | ||
| 30 | + :disableRange="false" | ||
| 31 | + :disableStream="false" | ||
| 32 | + :disableAutoFetch="false" | ||
| 33 | + @onProgress="handleProgress" | ||
| 34 | + @onComplete="handleComplete" | ||
| 35 | + @onScroll="handleScroll" | ||
| 36 | + @onPageChange="handlePageChange" | ||
| 37 | + @onPdfInit="handlePdfInit" | ||
| 38 | + @onError="handlePdfError" /> | ||
| 22 | 39 | ||
| 23 | <!-- 错误状态显示 --> | 40 | <!-- 错误状态显示 --> |
| 24 | <div v-if="loadingError" class="error-container"> | 41 | <div v-if="loadingError" class="error-container"> |
| ... | @@ -34,7 +51,7 @@ | ... | @@ -34,7 +51,7 @@ |
| 34 | </div> | 51 | </div> |
| 35 | 52 | ||
| 36 | <!-- 关闭按钮 --> | 53 | <!-- 关闭按钮 --> |
| 37 | - <van-button class="close-btn" type="default" icon="cross" round @click="emit('update:show', false)" /> | 54 | + <van-button class="close-btn" type="default" icon="cross" round @click="handleClose" /> |
| 38 | 55 | ||
| 39 | <!-- 缩放控制按钮 --> | 56 | <!-- 缩放控制按钮 --> |
| 40 | <div v-if="!loading && !loadingError" class="zoom-controls"> | 57 | <div v-if="!loading && !loadingError" class="zoom-controls"> |
| ... | @@ -70,7 +87,7 @@ | ... | @@ -70,7 +87,7 @@ |
| 70 | </template> | 87 | </template> |
| 71 | 88 | ||
| 72 | <script setup> | 89 | <script setup> |
| 73 | -import { ref, watch, nextTick } from 'vue'; | 90 | +import { ref, watch, nextTick, onUnmounted } from 'vue'; |
| 74 | import PDF from "pdf-vue3"; | 91 | import PDF from "pdf-vue3"; |
| 75 | 92 | ||
| 76 | /** | 93 | /** |
| ... | @@ -102,7 +119,7 @@ const props = defineProps({ | ... | @@ -102,7 +119,7 @@ const props = defineProps({ |
| 102 | /** | 119 | /** |
| 103 | * 事件定义 | 120 | * 事件定义 |
| 104 | */ | 121 | */ |
| 105 | -const emit = defineEmits(['update:show', 'onLoad', 'onProgress', 'onComplete']); | 122 | +const emit = defineEmits(['update:show', 'onLoad', 'onProgress', 'onComplete', 'onClose', 'onDestroy']); |
| 106 | 123 | ||
| 107 | // 响应式数据 | 124 | // 响应式数据 |
| 108 | const loading = ref(true); | 125 | const loading = ref(true); |
| ... | @@ -111,6 +128,7 @@ const loadingError = ref(false); | ... | @@ -111,6 +128,7 @@ const loadingError = ref(false); |
| 111 | const errorMessage = ref(''); | 128 | const errorMessage = ref(''); |
| 112 | const zoomLevel = ref(1); // 缩放级别,1为100% | 129 | const zoomLevel = ref(1); // 缩放级别,1为100% |
| 113 | const scrollPosition = ref({ x: 0, y: 0 }); // 记录滚动位置 | 130 | const scrollPosition = ref({ x: 0, y: 0 }); // 记录滚动位置 |
| 131 | +const pdfRef = ref(null); // PDF组件引用 | ||
| 114 | 132 | ||
| 115 | // 超时处理相关 | 133 | // 超时处理相关 |
| 116 | const loadingTimeout = ref(30000); // 超时时间,默认30秒 | 134 | const loadingTimeout = ref(30000); // 超时时间,默认30秒 |
| ... | @@ -131,13 +149,21 @@ watch(() => props.show, (newVal) => { | ... | @@ -131,13 +149,21 @@ watch(() => props.show, (newVal) => { |
| 131 | errorMessage.value = ''; | 149 | errorMessage.value = ''; |
| 132 | zoomLevel.value = 1; // 重置缩放级别 | 150 | zoomLevel.value = 1; // 重置缩放级别 |
| 133 | } else if (!newVal) { | 151 | } else if (!newVal) { |
| 134 | - // 弹窗关闭时重置状态 | 152 | + // 弹窗关闭时重置状态并清理资源 |
| 135 | clearAllTimers(); // 清除计时器 | 153 | clearAllTimers(); // 清除计时器 |
| 136 | - loading.value = true; | 154 | + |
| 137 | - loadingError.value = false; | 155 | + // 延迟清理,确保PDF组件有时间完成内部清理 |
| 138 | - loadingProgress.value = 0; | 156 | + setTimeout(() => { |
| 139 | - errorMessage.value = ''; | 157 | + loading.value = false; |
| 140 | - zoomLevel.value = 1; // 重置缩放级别 | 158 | + loadingError.value = false; |
| 159 | + loadingProgress.value = 0; | ||
| 160 | + errorMessage.value = ''; | ||
| 161 | + zoomLevel.value = 1; // 重置缩放级别 | ||
| 162 | + scrollPosition.value = { x: 0, y: 0 }; // 重置滚动位置 | ||
| 163 | + | ||
| 164 | + // 触发关闭销毁事件,通知父组件清理引用 | ||
| 165 | + emit('onClose'); | ||
| 166 | + }, 100); // 100ms延迟,给PDF组件时间清理 | ||
| 141 | } | 167 | } |
| 142 | }); | 168 | }); |
| 143 | 169 | ||
| ... | @@ -302,6 +328,28 @@ const retryLoad = () => { | ... | @@ -302,6 +328,28 @@ const retryLoad = () => { |
| 302 | }; | 328 | }; |
| 303 | 329 | ||
| 304 | /** | 330 | /** |
| 331 | + * 处理关闭弹窗 | ||
| 332 | + */ | ||
| 333 | +const handleClose = () => { | ||
| 334 | + // 先清理所有计时器 | ||
| 335 | + clearAllTimers(); | ||
| 336 | + | ||
| 337 | + // 如果PDF组件存在,尝试清理其内部状态 | ||
| 338 | + if (pdfRef.value && typeof pdfRef.value.destroy === 'function') { | ||
| 339 | + try { | ||
| 340 | + pdfRef.value.destroy(); | ||
| 341 | + } catch (error) { | ||
| 342 | + console.warn('PDF组件销毁时出现警告:', error); | ||
| 343 | + } | ||
| 344 | + } | ||
| 345 | + | ||
| 346 | + // 使用nextTick确保在DOM更新前完成清理 | ||
| 347 | + nextTick(() => { | ||
| 348 | + emit('update:show', false); | ||
| 349 | + }); | ||
| 350 | +}; | ||
| 351 | + | ||
| 352 | +/** | ||
| 305 | * 放大PDF | 353 | * 放大PDF |
| 306 | */ | 354 | */ |
| 307 | const zoomIn = () => { | 355 | const zoomIn = () => { | ... | ... |
-
Please register or login to post a comment