前提
页面内容首先通过请求获取,获取完成后,将Markdown文本通过marked.js将Markdown文本转化为HTML。
import {marked} from 'marked'
content.value = marked(contentForm.content)
之后再通过v-html渲染内容,将HTML渲染至页面上
<div
v-html="content"
class="markdown-body"
></div>
对于页面中的代码,通过HighLight.js进行高亮显示。
let highlight = function highlight() {
// 获取代码块
let preEle = document.querySelectorAll('pre')
// 对每个代码块执行高亮操作
preEle.forEach(el => {
hljs.highlightBlock(el)
})
}
问题所在
然而,页面上直接写静态文本时,代码可以正常高亮;但当页面内容通过v-html进行渲染时,代码没有高亮。
onMounted(() => {
nextTick(() => {
highlight()
})
})
出现原因
由于v-html是异步渲染的,在onMounted周期执行代码可能不能正确的获取到pre元素,即使加上nextTick使DOM全部挂载完成后也可能获取不到。
解决方法
1.使用watch监听内容,当页面内容发生变化时再渲染
watch(content, () => {
nextTick(() => {
highlight()
})
})
2.使用 MutationObserver 监听 DOM 变化,当 pre 元素被添加到页面中时再执行高亮操作
onMounted(() => {
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.addedNodes.length) {
nextTick(() => {
highlight()
})
}
})
})
observer.observe(document.body, {
childList: true,
subtree: true
})
})
3.在onUpdated周期内执行
onUpdated(() => {
highlight()
})