Skip to content

Commit ce3dbc7

Browse files
committed
fix: script not works in page
1 parent fbc7855 commit ce3dbc7

3 files changed

Lines changed: 56 additions & 4 deletions

File tree

index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
font-family: Arial, sans-serif;
2020
}
2121

22-
/* SVG版本 - 更精确的Android风格 */
2322
.loader {
2423
width: 60px;
2524
height: 60px;

src/page/page.vue

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts" setup>
2-
import { ref, watch } from 'vue';
2+
import { onMounted, onUnmounted, ref, shallowRef, watch } from 'vue';
33
import { useRoute, useRouter } from 'vue-router';
44
import { get_file } from '../main';
55
import { config } from '../../package.json';
@@ -22,10 +22,21 @@
2222
else
2323
$content.value = content;
2424
}, { immediate: true });
25+
26+
const page = shallowRef<HTMLDivElement>();
27+
onMounted(() => {
28+
// @ts-ignore
29+
globalThis.pdocument = page.value?.shadowRoot;
30+
})
31+
32+
onUnmounted(() => {
33+
// @ts-ignore
34+
delete globalThis.pdocument;
35+
})
2536
</script>
2637

2738
<template>
28-
<div class="page-content" v-render="$content" />
39+
<div class="page-content" ref="page" v-render="$content" />
2940
</template>
3041

3142
<style lang="scss">

src/utils/vue.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { computed, type ComputedRef, type Directive } from "vue";
1+
import { computed, nextTick, type ComputedRef, type Directive } from "vue";
22

33
export function debounceComputed<T>(func: () => T, wait = 1000): ComputedRef<T> {
44
let lastCacheTime = Date.now();
@@ -19,14 +19,56 @@ export function debounceComputed<T>(func: () => T, wait = 1000): ComputedRef<T>
1919
});
2020
}
2121

22+
async function execScript(scr: HTMLScriptElement, shadowRoot: ShadowRoot){
23+
let text = scr.textContent;
24+
if (scr.src) {
25+
const fe = await fetch(scr.src);
26+
if(!fe.ok) throw new Error('Failed to fetch script');
27+
text = await fe.text();
28+
}
29+
const script = document.createElement('script');
30+
script.textContent = text;
31+
shadowRoot.appendChild(script);
32+
}
33+
34+
function handleShadow(el: HTMLElement) {
35+
requestAnimationFrame(async () => {
36+
const scrs = el.shadowRoot?.querySelectorAll('script');
37+
// @ts-ignore store
38+
el.hasScript = !!scrs?.length;
39+
40+
// render script
41+
const defer = [] as HTMLScriptElement[];
42+
for (const scr of scrs || []) {
43+
// defer: exec script after dom render
44+
if (scr.defer) defer.push(scr);
45+
46+
// async: create async corutine to exec script
47+
if (scr.async) execScript(scr, el.shadowRoot!);
48+
49+
// exec script immediately
50+
await execScript(scr, el.shadowRoot!);
51+
}
52+
53+
// exec deferred script
54+
for (const scr of defer) execScript(scr, el.shadowRoot!);
55+
});
56+
}
57+
2258
export const vRender: Directive<HTMLElement, string> = {
2359
mounted(el, binding){
2460
el.shadowRoot || el.attachShadow({ mode: 'open' });
2561
el.shadowRoot!.innerHTML = binding.value;
62+
63+
handleShadow(el);
2664
},
2765

2866
updated(el, binding){
67+
// @ts-ignore store
68+
if(el.hasScript) location.reload(); // prevent JS leak
2969
el.shadowRoot!.innerHTML = binding.value;
70+
71+
handleShadow(el);
3072
}
3173
}
3274

0 commit comments

Comments
 (0)