feat: 无界渲染适配器
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
"dependencies": {
|
||||
"postmate": "catalog:",
|
||||
"vue": "catalog:",
|
||||
"wujie-vue3": "1.0.24"
|
||||
"wujie-vue3": "1.0.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@farmfe/cli": "^1.0.4",
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted } from 'vue';
|
||||
|
||||
import WujieVue from 'wujie-vue3';
|
||||
|
||||
import { version } from '/package.json';
|
||||
|
||||
const props = defineProps<{
|
||||
[key: string]: any;
|
||||
accessToken?: string;
|
||||
applicationId: number | string;
|
||||
degrade?: boolean;
|
||||
fileId: number | string;
|
||||
name: string;
|
||||
projectId: number | string;
|
||||
sync: boolean;
|
||||
url: string;
|
||||
}>();
|
||||
|
||||
console.log('props', props);
|
||||
|
||||
const { bus } = WujieVue;
|
||||
|
||||
// 生命周期钩子
|
||||
const beforeLoad = (appWindow: Window) => {
|
||||
console.log(`${props.name} 开始加载`, appWindow);
|
||||
};
|
||||
|
||||
const afterMount = (appWindow: Window) => {
|
||||
console.log(`${props.name} 加载完成`, appWindow);
|
||||
};
|
||||
|
||||
// 事件处理
|
||||
const handleMessage = (data: any) => {
|
||||
console.log('收到子应用消息:', data);
|
||||
};
|
||||
|
||||
// 准备传递给子应用的数据
|
||||
const subAppProps = {
|
||||
...props,
|
||||
adapterInfo: {
|
||||
version,
|
||||
},
|
||||
};
|
||||
|
||||
// 监听子应用的事件
|
||||
const handleReady = (data: any) => {
|
||||
console.log('子应用就绪:', data);
|
||||
// 可以在这里执行一些操作
|
||||
};
|
||||
|
||||
const handleRenderSuccess = () => {
|
||||
console.log('子应用渲染成功');
|
||||
// 通知父应用
|
||||
};
|
||||
|
||||
const handleRenderFail = (error: any) => {
|
||||
console.error('子应用渲染失败:', error);
|
||||
// 处理错误情况
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 注册事件监听
|
||||
bus.$on('message', handleMessage);
|
||||
bus.$on('ready', handleReady);
|
||||
bus.$on('render-success', handleRenderSuccess);
|
||||
bus.$on('render-fail', handleRenderFail);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 移除所有事件监听
|
||||
bus.$off('message', handleMessage);
|
||||
bus.$off('ready', handleReady);
|
||||
bus.$off('render-success', handleRenderSuccess);
|
||||
bus.$off('render-fail', handleRenderFail);
|
||||
});
|
||||
|
||||
// 在子应用加载前执行的脚本,用于修补 adoptedStyleSheets
|
||||
const execBeforeLoading = `
|
||||
// 修补 CSSStyleSheet API
|
||||
if (window.CSSStyleSheet && CSSStyleSheet.prototype.replaceSync) {
|
||||
const originalReplaceSync = CSSStyleSheet.prototype.replaceSync;
|
||||
CSSStyleSheet.prototype.replaceSync = function(text) {
|
||||
try {
|
||||
return originalReplaceSync.call(this, text);
|
||||
} catch (e) {
|
||||
console.warn('CSSStyleSheet.replaceSync 被拦截:', e);
|
||||
|
||||
// 降级处理:创建普通样式标签
|
||||
const style = document.createElement('style');
|
||||
style.textContent = text;
|
||||
document.head.appendChild(style);
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 替换 adoptedStyleSheets 的 setter
|
||||
try {
|
||||
if (Document.prototype.hasOwnProperty('adoptedStyleSheets')) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'adoptedStyleSheets');
|
||||
if (descriptor && descriptor.set) {
|
||||
const originalSetter = descriptor.set;
|
||||
descriptor.set = function(sheets) {
|
||||
try {
|
||||
originalSetter.call(this, sheets);
|
||||
} catch (e) {
|
||||
console.warn('adoptedStyleSheets setter 被拦截:', e);
|
||||
// 不抛出错误,静默失败
|
||||
}
|
||||
};
|
||||
Object.defineProperty(Document.prototype, 'adoptedStyleSheets', descriptor);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('无法修补 adoptedStyleSheets:', e);
|
||||
}
|
||||
`;
|
||||
</script>
|
||||
<template>
|
||||
<div style="width: 100%; height: 100%">
|
||||
<WujieVue
|
||||
:name="name"
|
||||
:url="url"
|
||||
:sync="sync"
|
||||
:degrade="degrade"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:props="subAppProps"
|
||||
:before-load="beforeLoad"
|
||||
:after-mount="afterMount"
|
||||
:plugins="[
|
||||
{
|
||||
cssLoader: (code, url, jsdom, appWindow) => {
|
||||
console.log('cssLoader', code, url, jsdom, appWindow);
|
||||
|
||||
try {
|
||||
// 尝试在子应用窗口中创建样式
|
||||
if (appWindow && appWindow.document) {
|
||||
const style = appWindow.document.createElement('style');
|
||||
style.textContent = code;
|
||||
appWindow.document.head.appendChild(style);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果没有 appWindow,尝试使用 jsdom
|
||||
if (jsdom && jsdom.window && jsdom.window.document) {
|
||||
const style = jsdom.window.document.createElement('style');
|
||||
style.textContent = code;
|
||||
jsdom.window.document.head.appendChild(style);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 都不可用时,返回 false 让 wujie 使用默认处理
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.warn('CSS 处理错误:', error);
|
||||
return false; // 让 wujie 使用默认处理
|
||||
}
|
||||
},
|
||||
},
|
||||
]"
|
||||
:degrade="true"
|
||||
:exec-before-loading="execBeforeLoading"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,93 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted } from 'vue';
|
||||
|
||||
import WujieVue from 'wujie-vue3';
|
||||
|
||||
import { version } from '/package.json';
|
||||
|
||||
const props = defineProps<{
|
||||
[key: string]: any;
|
||||
accessToken?: string;
|
||||
applicationId: number | string;
|
||||
degrade?: boolean;
|
||||
fileId: number | string;
|
||||
name: string;
|
||||
projectId: number | string;
|
||||
sync: boolean;
|
||||
url: string;
|
||||
}>();
|
||||
|
||||
console.log('props', props);
|
||||
|
||||
const { bus } = WujieVue;
|
||||
|
||||
// 生命周期钩子
|
||||
const beforeLoad = (appWindow: Window) => {
|
||||
console.log(`${props.name} 开始加载`, appWindow);
|
||||
};
|
||||
|
||||
const afterMount = (appWindow: Window) => {
|
||||
console.log(`${props.name} 加载完成`, appWindow);
|
||||
};
|
||||
|
||||
// 事件处理
|
||||
const handleMessage = (data: any) => {
|
||||
console.log('收到子应用消息:', data);
|
||||
};
|
||||
|
||||
// 准备传递给子应用的数据
|
||||
const subAppProps = {
|
||||
...props,
|
||||
adapterInfo: {
|
||||
version,
|
||||
},
|
||||
};
|
||||
|
||||
// 监听子应用的事件
|
||||
const handleReady = (data: any) => {
|
||||
console.log('子应用就绪:', data);
|
||||
// 可以在这里执行一些操作
|
||||
};
|
||||
|
||||
const handleRenderSuccess = () => {
|
||||
console.log('子应用渲染成功');
|
||||
// 通知父应用
|
||||
};
|
||||
|
||||
const handleRenderFail = (error: any) => {
|
||||
console.error('子应用渲染失败:', error);
|
||||
// 处理错误情况
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 注册事件监听
|
||||
bus.$on('message', handleMessage);
|
||||
bus.$on('ready', handleReady);
|
||||
bus.$on('render-success', handleRenderSuccess);
|
||||
bus.$on('render-fail', handleRenderFail);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 移除所有事件监听
|
||||
bus.$off('message', handleMessage);
|
||||
bus.$off('ready', handleReady);
|
||||
bus.$off('render-success', handleRenderSuccess);
|
||||
bus.$off('render-fail', handleRenderFail);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div style="width: 100%; height: 100%">
|
||||
<WujieVue
|
||||
:name="name"
|
||||
:url="url"
|
||||
:sync="sync"
|
||||
:degrade="true"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:props="subAppProps"
|
||||
:before-load="beforeLoad"
|
||||
:after-mount="afterMount"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -17,10 +17,10 @@ const props = defineProps<{
|
||||
url: string;
|
||||
}>();
|
||||
|
||||
const { bus, preloadApp } = WujieVue;
|
||||
|
||||
console.log('props', props);
|
||||
|
||||
const { bus } = WujieVue;
|
||||
|
||||
// 生命周期钩子
|
||||
const beforeLoad = (appWindow: Window) => {
|
||||
console.log(`${props.name} 开始加载`, appWindow);
|
||||
@@ -30,9 +30,9 @@ const afterMount = (appWindow: Window) => {
|
||||
console.log(`${props.name} 加载完成`, appWindow);
|
||||
};
|
||||
|
||||
// 定义自定义 fetch 函数
|
||||
const customFetch = (url: string, options?: any) => {
|
||||
return window.fetch(url, { ...options, credentials: 'include' });
|
||||
// 事件处理
|
||||
const handleMessage = (data: any) => {
|
||||
console.log('收到子应用消息:', data);
|
||||
};
|
||||
|
||||
// 准备传递给子应用的数据
|
||||
@@ -43,35 +43,36 @@ const subAppProps = {
|
||||
},
|
||||
};
|
||||
|
||||
// 预加载应用
|
||||
// 监听子应用的事件
|
||||
const handleReady = (data: any) => {
|
||||
console.log('子应用就绪:', data);
|
||||
// 可以在这里执行一些操作
|
||||
};
|
||||
|
||||
const handleRenderSuccess = () => {
|
||||
console.log('子应用渲染成功');
|
||||
// 通知父应用
|
||||
};
|
||||
|
||||
const handleRenderFail = (error: any) => {
|
||||
console.error('子应用渲染失败:', error);
|
||||
// 处理错误情况
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 注册事件监听
|
||||
bus.$on('message', (data: any) => {
|
||||
console.log('收到子应用消息:', data);
|
||||
});
|
||||
bus.$on('ready', (data: any) => {
|
||||
console.log('子应用就绪:', data);
|
||||
});
|
||||
bus.$on('render-success', () => {
|
||||
console.log('子应用渲染成功');
|
||||
});
|
||||
bus.$on('render-fail', (error: any) => {
|
||||
console.error('子应用渲染失败:', error);
|
||||
});
|
||||
|
||||
// 预加载应用
|
||||
preloadApp({
|
||||
degrade: true,
|
||||
exec: true,
|
||||
fetch: customFetch,
|
||||
name: props.name,
|
||||
url: props.url,
|
||||
});
|
||||
bus.$on('message', handleMessage);
|
||||
bus.$on('ready', handleReady);
|
||||
bus.$on('render-success', handleRenderSuccess);
|
||||
bus.$on('render-fail', handleRenderFail);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 移除所有事件监听
|
||||
bus.$offAll();
|
||||
bus.$off('message', handleMessage);
|
||||
bus.$off('ready', handleReady);
|
||||
bus.$off('render-success', handleRenderSuccess);
|
||||
bus.$off('render-fail', handleRenderFail);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -81,13 +82,12 @@ onBeforeUnmount(() => {
|
||||
:name="name"
|
||||
:url="url"
|
||||
:sync="sync"
|
||||
:degrade="true"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:degrade="degrade"
|
||||
:props="subAppProps"
|
||||
:before-load="beforeLoad"
|
||||
:after-mount="afterMount"
|
||||
:fetch="customFetch"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user