@@ -19,22 +19,30 @@ export default {
1919 const route = useRoute ()
2020
2121 // 处理交互式代码块的函数
22- const handleCodeBlocks = async () => {
22+ const handleCodeBlocks = async (force = false ) => {
2323 await nextTick ()
24- await processInteractiveCodeBlocks ()
24+ await processInteractiveCodeBlocks (force )
2525 }
2626
2727 // 页面首次加载时处理
28- onMounted (handleCodeBlocks)
28+ onMounted (() => handleCodeBlocks () )
2929
3030 // DOM 更新后处理(包括路由变化)
31- onUpdated (handleCodeBlocks)
31+ onUpdated (() => handleCodeBlocks () )
3232
3333 // 监听路由变化
3434 watch (() => route .path , async () => {
35- await handleCodeBlocks ()
35+ await handleCodeBlocks (true ) // 路由变化时强制重新处理
3636 }, { flush: ' post' })
3737
38+ // 热更新时的额外处理
39+ if (import .meta.hot) {
40+ import .meta .hot .on ('vite :afterUpdate ', () => {
41+ // 延迟处理,确保 DOM 已经更新
42+ setTimeout (() => handleCodeBlocks (true ), 100)
43+ })
44+ }
45+
3846 return {}
3947 }
4048}
@@ -52,7 +60,7 @@ function base64DecodeUtf8(str) {
5260}
5361
5462// 处理交互式代码块的函数
55- async function processInteractiveCodeBlocks () {
63+ async function processInteractiveCodeBlocks (force = false ) {
5664 // 查找所有需要处理的标记
5765 const blocks = document .querySelectorAll (' .interactive-code-block' )
5866
@@ -63,7 +71,7 @@ async function processInteractiveCodeBlocks() {
6371
6472 blocks .forEach ((block , index ) => {
6573 // 检查是否已经处理过了(避免重复处理)
66- if (block .querySelector (' .interactive-code' )) {
74+ if (! force && block .querySelector (' .interactive-code' )) {
6775 return
6876 }
6977
@@ -82,6 +90,17 @@ async function processInteractiveCodeBlocks() {
8290 const decodedCode = base64DecodeUtf8 (encodedCode)
8391 const decodedTitle = encodedTitle ? base64DecodeUtf8 (encodedTitle) : ' '
8492
93+ // 如果是强制重新处理,需要先清理旧的实例
94+ if (force && block ._vueApp ) {
95+ try {
96+ block ._vueApp .unmount ()
97+ } catch (e) {
98+ // 忽略卸载错误
99+ console .warn (' Warning during Vue app unmount:' , e)
100+ }
101+ delete block ._vueApp
102+ }
103+
85104 // 清空原有内容
86105 block .innerHTML = ' '
87106
@@ -93,6 +112,9 @@ async function processInteractiveCodeBlocks() {
93112 runnable: runnable // 传递 runnable 属性
94113 })
95114
115+ // 保存应用实例的引用,便于后续清理
116+ block ._vueApp = app
117+
96118 // 挂载到当前位置
97119 app .mount (block)
98120 } catch (error) {
0 commit comments