You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免向<head>添加CSS时的内存泄漏?Vue钩子优化求助

解决Vue全局样式钩子的内存泄漏问题

你的问题核心在于只跟踪了样式是否被注入,没管理使用该样式的组件数量,导致组件卸载后样式标签无法被清理。用引用计数的方式就能解决,而且不会阻碍垃圾回收——因为我们不需要存储组件实例,只记录使用次数即可。

修改后的实现如下:

// 用Map存储样式的引用计数和对应的style元素,key是css字符串
const injectedStyles = new Map<string, { count: number; element: HTMLStyleElement }>()

function useGlobalStyles(cssStyles: string) {
    onBeforeMount(() => {
        const existingEntry = injectedStyles.get(cssStyles)
        if (existingEntry) {
            // 已有组件在用这个样式,计数+1
            existingEntry.count++
            return
        }

        // 第一次注入,创建style元素并添加到head
        const styleEl = document.createElement('style')
        styleEl.textContent = cssStyles
        document.head.appendChild(styleEl)

        // 存入Map,初始计数为1
        injectedStyles.set(cssStyles, {
            count: 1,
            element: styleEl
        })
    })

    // 组件卸载时处理计数和样式清理
    onUnmounted(() => {
        const entry = injectedStyles.get(cssStyles)
        if (!entry) return

        entry.count--
        // 当计数为0时,移除style标签并从Map中删除记录
        if (entry.count === 0) {
            document.head.removeChild(entry.element)
            injectedStyles.delete(cssStyles)
        }
    })
}

关键说明:

  • 用Map替代Set,每个样式条目存储引用计数和对应的DOM元素,完全不涉及组件实例的存储,不会干扰GC
  • 组件挂载时,若样式已存在就增加计数,不存在则创建并初始化计数
  • 组件卸载时减少计数,只有当所有使用该样式的组件都卸载后(计数归0),才真正删除style标签并清理Map中的记录
  • 这种方式既保证了全局样式不会重复注入,又能在无人使用时自动清理,彻底解决内存泄漏问题

内容的提问来源于stack exchange,提问作者Alex l.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 04:06:26