Vue项目中highlight.js高亮代码块遇页面回退消失及动态高亮需求
解决方案
核心问题分析
- 固定2秒的
setTimeout完全不可靠:DOM更新时机不固定,尤其是浏览器回退时(可能使用页面缓存),延迟执行时DOM可能已经被重新渲染或移除,导致代码消失。 - 页面回退时,浏览器可能通过BF Cache(后退/前进缓存)复用页面,此时组件不会触发
onMounted,原有的高亮逻辑无法执行。
具体修复步骤
- 用
nextTick替代setTimeout:确保DOM完全更新后再执行高亮操作,这是Vue中等待DOM更新的标准方式。 - 监听
pageshow事件:处理浏览器回退时的页面复用场景,重新触发高亮。 - 高亮前清理已有样式:避免重复高亮导致的DOM结构异常。
修改后的组件代码
import { defineComponent, h, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'; import highlight from 'highlight.js' export const WYSIWYG = defineComponent({ name: 'WYSIWYG', props: { content: { type: String, required: true }, }, setup(props) { const root = ref<HTMLElement>(null); const highlightCodes = async () => { // 等待DOM更新完成 await nextTick(); const codeElements = root.value?.querySelectorAll('pre code'); if (!codeElements) return; codeElements.forEach((el: HTMLElement) => { // 先移除已有的高亮样式,避免重复处理 el.classList.remove('hljs'); el.innerHTML = el.textContent || ''; // 重新执行高亮 highlight.highlightElement(el); }); }; const handlePageShow = () => { // 页面从缓存恢复时重新高亮 highlightCodes(); }; onMounted(() => { highlightCodes(); window.addEventListener('pageshow', handlePageShow); }); onUnmounted(() => { window.removeEventListener('pageshow', handlePageShow); }); // 监听content变化,实时高亮 watch(() => props.content, highlightCodes, { immediate: true }); return function render() { return h('div', { class: 'WYSIWYG', ref: root, innerHTML: props.content }); }; }, });
关键说明
nextTick:Vue在更新DOM后会触发nextTick回调,确保我们操作的是最新的DOM元素,完全替代不可靠的固定延迟。pageshow事件:当页面从BF Cache中恢复时会触发该事件,此时重新执行高亮逻辑,解决回退时代码消失的问题。- 清理原有高亮:每次处理前重置code元素的内容和样式,避免重复调用
highlightElement导致的DOM结构混乱。
内容的提问来源于stack exchange,提问作者Bruno Francisco
相关产品推荐
相关产品推荐

