欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > 前端远端SDK组件加载方案

前端远端SDK组件加载方案

2025/2/27 6:19:47 来源:https://blog.csdn.net/zSY_snake/article/details/141639115  浏览:    关键词:前端远端SDK组件加载方案

背景

  作者维护的可视化搭建平台所提供的投放数据配置表单是基于搭建物料中配置的JSON Schema经过统一的渲染生成的,这就意味着:表单项的类型是预先约定好的,虽然这可以满足业务绝大部分的诉求,但是总有一些高度定制的配置项需要支持业务自定义。作为一个通用的平台,内部耦合业务逻辑是个很愚蠢的办法,所以便开了业务自定义扩展渲染组件的口子。

原理

  支持UMD类型的像InputSelect这些基础组件一样的可用于表单渲染的组件通过cdn远程加载。

组件设计

  要想使用UMD的组件首先要做一个容器组件用于渲染。同时该容器组件又要用于表单渲染。所以组件props设计如下:

interface PropsType {render?: {name: string;  // library name entry: string; // 自定义渲染组件 umd 格式 urlstyle: string; // 自定义渲染组件 css文件};value: any;onChange: (value: any) => void;[x: string]: any; // 业务自定义参数
}

render参数用于组件渲染,其他参数用于组件逻辑

组件核心逻辑

CustomRender

const CustomRender: React.FC<PropsType> = (props) => {const {render,...otherProps} = props;const [Com, setCom] = useState<any>();useEffect(() => {if (!render?.entry) {return;}(async () => {// 加载UMD组件const C = await importScript(render?.entry, render?.name);// 加载组件样式render?.style && importStyle(render?.style);setCom(() => C);})();}, [render?.entry]);return (<ErrorBoundary fallback={<div>配置项加载失败</div>}><div>{Com ? <Com {...otherProps} /> : <div>加载中...</div>}</div></ErrorBoundary>);
};

importScript

export const importScript = (() => {// 自执行函数,创建一个闭包,保存 cache 结果const cache: { [x: string]: any } = {};return (url: string, name?: string) => {// 如果有缓存,则直接返回缓存内容if (cache[url]) return Promise.resolve(cache[url]);return new Promise((resolve, reject) => {// 保存最后一个 window 属性 keyconst lastWindowKey = Object.keys(window).pop();// 创建 scriptconst script = document.createElement('script');script.setAttribute('src', url);document.head.appendChild(script);// 监听加载完成事件script.addEventListener('load', () => {document.head.removeChild(script);// 最后一个新增的 key,就是 umd 挂载的,可自行验证const newLastWindowKey = name || Object.keys(window).pop();console.log('newLastWindowKey', newLastWindowKey);// 获取到导出的组件const res = lastWindowKey !== newLastWindowKey ? window[newLastWindowKey] : {};const Com = res.default ? res.default : res;cache[url] = Com;resolve(Com);});// 监听加载失败情况script.addEventListener('error', (error) => {reject(error);});});};
})();

importStyle

export const importStyle = (() => {return (url: string) => {if (document.querySelector(`link[href='${url}']`)) {return;}return new Promise((resolve, reject) => {// 创建 linkconst link = document.createElement('link');link.setAttribute('rel', 'stylesheet');link.setAttribute('href', url);document.head.appendChild(link);// 监听加载完成事件link.addEventListener('load', () => {resolve(link);});// 监听加载失败情况link.addEventListener('error', (error) => {reject(error);});});};
})();

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com