fix: 添加组件卸载时的资源清理逻辑
在TEditor、MarqueeField、VideoField组件和主视图页面中添加onUnmounted钩子 清理tinymce实例、定时器和视频播放器资源,防止内存泄漏
Showing
4 changed files
with
61 additions
and
10 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-29 14:31:20 | 2 | * @Date: 2022-08-29 14:31:20 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-11-23 10:49:41 | 4 | + * @LastEditTime: 2025-09-30 22:13:39 |
| 5 | * @FilePath: /data-table/src/components/MarqueeField/index.vue | 5 | * @FilePath: /data-table/src/components/MarqueeField/index.vue |
| 6 | * @Description: 跑马灯控件 | 6 | * @Description: 跑马灯控件 |
| 7 | --> | 7 | --> |
| ... | @@ -32,6 +32,14 @@ onMounted(() => { | ... | @@ -32,6 +32,14 @@ onMounted(() => { |
| 32 | ScrollUp(); | 32 | ScrollUp(); |
| 33 | }); | 33 | }); |
| 34 | 34 | ||
| 35 | +onUnmounted(() => { | ||
| 36 | + // 清理定时器 | ||
| 37 | + if (intNum.value) { | ||
| 38 | + clearInterval(intNum.value); | ||
| 39 | + intNum.value = null; | ||
| 40 | + } | ||
| 41 | +}); | ||
| 42 | + | ||
| 35 | const top = computed(() => { | 43 | const top = computed(() => { |
| 36 | return -activeIndex.value * 30 + "px"; | 44 | return -activeIndex.value * 30 + "px"; |
| 37 | }); | 45 | }); | ... | ... |
| ... | @@ -346,6 +346,13 @@ onMounted(() => { | ... | @@ -346,6 +346,13 @@ onMounted(() => { |
| 346 | // tinymce.init({}); | 346 | // tinymce.init({}); |
| 347 | }); | 347 | }); |
| 348 | 348 | ||
| 349 | +onUnmounted(() => { | ||
| 350 | + // 清理tinymce实例 | ||
| 351 | + if (tinymce.activeEditor) { | ||
| 352 | + tinymce.activeEditor.destroy(); | ||
| 353 | + } | ||
| 354 | +}); | ||
| 355 | + | ||
| 349 | // 设置值 | 356 | // 设置值 |
| 350 | const handleSetContent = (content) => { | 357 | const handleSetContent = (content) => { |
| 351 | tinymce.activeEditor.setContent(content); | 358 | tinymce.activeEditor.setContent(content); | ... | ... |
| ... | @@ -21,7 +21,7 @@ | ... | @@ -21,7 +21,7 @@ |
| 21 | */ | 21 | */ |
| 22 | import "mui-player/dist/mui-player.min.css"; | 22 | import "mui-player/dist/mui-player.min.css"; |
| 23 | import MuiPlayer from "mui-player"; | 23 | import MuiPlayer from "mui-player"; |
| 24 | -import { onMounted } from "vue"; | 24 | +import { onMounted, onUnmounted } from "vue"; |
| 25 | import { useEventListener } from "@/composables"; | 25 | import { useEventListener } from "@/composables"; |
| 26 | 26 | ||
| 27 | // 视频基础属性 | 27 | // 视频基础属性 |
| ... | @@ -31,8 +31,18 @@ const props = defineProps({ | ... | @@ -31,8 +31,18 @@ const props = defineProps({ |
| 31 | // 视频播放事件回调 | 31 | // 视频播放事件回调 |
| 32 | const emit = defineEmits(["active"]); | 32 | const emit = defineEmits(["active"]); |
| 33 | let video = null; | 33 | let video = null; |
| 34 | +let muiPlayerInstance = null; | ||
| 35 | + | ||
| 36 | +/** | ||
| 37 | + * 视频播放事件处理函数 | ||
| 38 | + */ | ||
| 39 | +const handleVideoPlay = () => { | ||
| 40 | + props.item.value = { key: "video", value: "play" }; | ||
| 41 | + emit("active", props.item.value); | ||
| 42 | +}; | ||
| 43 | + | ||
| 34 | onMounted(() => { | 44 | onMounted(() => { |
| 35 | - const mp = new MuiPlayer({ | 45 | + muiPlayerInstance = new MuiPlayer({ |
| 36 | container: "#mui-player", | 46 | container: "#mui-player", |
| 37 | // title: props.item.component_props.title, | 47 | // title: props.item.component_props.title, |
| 38 | src: props.item.component_props.src, | 48 | src: props.item.component_props.src, |
| ... | @@ -45,12 +55,9 @@ onMounted(() => { | ... | @@ -45,12 +55,9 @@ onMounted(() => { |
| 45 | { attrKey: "x5-video-player-type", attrValue: "h5-page" }, | 55 | { attrKey: "x5-video-player-type", attrValue: "h5-page" }, |
| 46 | ], | 56 | ], |
| 47 | }); | 57 | }); |
| 48 | - video = mp.video(); | 58 | + video = muiPlayerInstance.video(); |
| 49 | //视频播放事件监听 | 59 | //视频播放事件监听 |
| 50 | - video.addEventListener("play", function () { | 60 | + video.addEventListener("play", handleVideoPlay); |
| 51 | - props.item.value = { key: "video", value: "play" }; | ||
| 52 | - emit("active", props.item.value); | ||
| 53 | - }); | ||
| 54 | // 配置16:9高度比 | 61 | // 配置16:9高度比 |
| 55 | const width = document.getElementById("mui-player").clientWidth; | 62 | const width = document.getElementById("mui-player").clientWidth; |
| 56 | const height = (width * 9) / 16; | 63 | const height = (width * 9) / 16; |
| ... | @@ -58,7 +65,16 @@ onMounted(() => { | ... | @@ -58,7 +65,16 @@ onMounted(() => { |
| 58 | }); | 65 | }); |
| 59 | 66 | ||
| 60 | onUnmounted(() => { | 67 | onUnmounted(() => { |
| 61 | - video.removeEventListener("play", function () {}); | 68 | + // 移除事件监听器 |
| 69 | + if (video) { | ||
| 70 | + video.removeEventListener("play", handleVideoPlay); | ||
| 71 | + } | ||
| 72 | + // 销毁MuiPlayer实例 | ||
| 73 | + if (muiPlayerInstance) { | ||
| 74 | + muiPlayerInstance.destroy(); | ||
| 75 | + muiPlayerInstance = null; | ||
| 76 | + } | ||
| 77 | + video = null; | ||
| 62 | }); | 78 | }); |
| 63 | </script> | 79 | </script> |
| 64 | 80 | ... | ... |
| ... | @@ -387,6 +387,9 @@ const collapseRef = ref(null); | ... | @@ -387,6 +387,9 @@ const collapseRef = ref(null); |
| 387 | 387 | ||
| 388 | const show_loading = ref(false); | 388 | const show_loading = ref(false); |
| 389 | 389 | ||
| 390 | +// 定时器ID,用于清理轮询 | ||
| 391 | +let subscribeCheckInterval = null; | ||
| 392 | + | ||
| 390 | onMounted(async () => { | 393 | onMounted(async () => { |
| 391 | // 显示加载动画 | 394 | // 显示加载动画 |
| 392 | show_loading.value = true; | 395 | show_loading.value = true; |
| ... | @@ -615,6 +618,14 @@ onMounted(async () => { | ... | @@ -615,6 +618,14 @@ onMounted(async () => { |
| 615 | }, false); | 618 | }, false); |
| 616 | }); | 619 | }); |
| 617 | 620 | ||
| 621 | +onUnmounted(() => { | ||
| 622 | + // 清理定时器 | ||
| 623 | + if (subscribeCheckInterval) { | ||
| 624 | + clearInterval(subscribeCheckInterval); | ||
| 625 | + subscribeCheckInterval = null; | ||
| 626 | + } | ||
| 627 | +}); | ||
| 628 | + | ||
| 618 | // 自定义失焦操作 | 629 | // 自定义失焦操作 |
| 619 | // const onBlur = async (item) => { | 630 | // const onBlur = async (item) => { |
| 620 | // console.warn(item); | 631 | // console.warn(item); |
| ... | @@ -637,7 +648,11 @@ onMounted(async () => { | ... | @@ -637,7 +648,11 @@ onMounted(async () => { |
| 637 | // 打开轮询用户是否关注 | 648 | // 打开轮询用户是否关注 |
| 638 | const onTap = () => { | 649 | const onTap = () => { |
| 639 | if (localStorage.getItem('weixin_subscribe') === '0') { | 650 | if (localStorage.getItem('weixin_subscribe') === '0') { |
| 640 | - setInterval(() => { | 651 | + // 清理之前的定时器(如果存在) |
| 652 | + if (subscribeCheckInterval) { | ||
| 653 | + clearInterval(subscribeCheckInterval); | ||
| 654 | + } | ||
| 655 | + subscribeCheckInterval = setInterval(() => { | ||
| 641 | checkUserSubscribe() | 656 | checkUserSubscribe() |
| 642 | }, 1000); | 657 | }, 1000); |
| 643 | } | 658 | } |
| ... | @@ -650,6 +665,11 @@ const checkUserSubscribe = () => { | ... | @@ -650,6 +665,11 @@ const checkUserSubscribe = () => { |
| 650 | // 标记用户已关注 | 665 | // 标记用户已关注 |
| 651 | localStorage.setItem('weixin_subscribe', 1); | 666 | localStorage.setItem('weixin_subscribe', 1); |
| 652 | show_qrcode.value = false; | 667 | show_qrcode.value = false; |
| 668 | + // 清理定时器 | ||
| 669 | + if (subscribeCheckInterval) { | ||
| 670 | + clearInterval(subscribeCheckInterval); | ||
| 671 | + subscribeCheckInterval = null; | ||
| 672 | + } | ||
| 653 | } | 673 | } |
| 654 | // 凭密码填写设置 | 674 | // 凭密码填写设置 |
| 655 | if (formSetting.value.mmtx_enable) { | 675 | if (formSetting.value.mmtx_enable) { | ... | ... |
-
Please register or login to post a comment