本文主要是介绍前端远端SDK组件加载方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
背景
作者维护的可视化搭建平台所提供的投放数据配置表单是基于搭建物料中配置的JSON Schema经过统一的渲染生成的,这就意味着:表单项的类型是预先约定好的,虽然这可以满足业务绝大部分的诉求,但是总有一些高度定制的配置项需要支持业务自定义。作为一个通用的平台,内部耦合业务逻辑是个很愚蠢的办法,所以便开了业务自定义扩展渲染组件的口子。
原理
支持UMD
类型的像Input
、Select
这些基础组件一样的可用于表单渲染的组件通过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);});});};
})();
这篇关于前端远端SDK组件加载方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!