vue-mod-page/src/components/Invoker.tsx

118 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
defineComponent,
onBeforeUpdate,
onUnmounted,
watch,
type PropType
} from "vue-demi";
import { ModContext } from "../types/ModContext";
import { InvokerItem } from "./InvokerItem";
let idCount = 0;
export type InvokerModName = string;
export default defineComponent({
props: {
height: {
type: String,
default: () => "auto",
},
scroll: {
type: Boolean,
default: () => false,
},
items: {
type: Array,
default: () => undefined as InvokerItem[] | undefined,
},
name: {
type: String as PropType<InvokerModName> | undefined,
default: () => undefined,
required: false,
}
},
emits: ["destroyed"],
setup(props, { slots, expose, emit }) {
/** Invoker实例ID */
const id = ++idCount;
/** vue实例上下文此处获取的是Receiver的vue组件实例 */
let receiver: ModContext | null = null;
window["MES_MOD_INVOKERS"] ||= {};
window["MES_MOD_INVOKERS"][id] = {
getRenderContext,
initFinish,
receiver,
};
/** 主动更新 */
function updateComponent() {
// 判断子页面vue对象是否存在
receiver?.Update(); // 强制渲染
}
// 子组件调用
function eventCallback(type: string, ...args: any[]) {
switch (type) {
case "created":
initFinish(args[0]);
break;
}
}
/** 当Receiver初始化完毕后触发 */
function initFinish(context: ModContext) {
receiver = context;
console.log('[Mod-Invoker]initFinish')
}
function getRefs() {
const refs = receiver?.refs;
if (!refs) throw new Error("[Mod-Invoker] Receiver not found");
return refs;
}
// vue3 渲染上下文
function getRenderContext() {
return props.items;
}
expose({
getRefs,
getRenderContext,
eventCallback,
initFinish,
});
watch(
() => props.items,
() => {
updateComponent();
}
);
onBeforeUpdate(() => {
});
onUnmounted(() => {
console.log("[Mod-Invoker] invoker-destroyed");
emit('destroyed');
});
return (h) => {
if (slots.default) {
return <div>{slots.default()}</div>;
}
return (
<iframe
src={props.url.replace('{id}',id.toString())}
scrolling={props.scroll ? "yes" : "no"}
style={`border: none; width: 100%; height: ${props.height}; `}
></iframe>
);
};
},
});