declare global {
interface Window {
TinyComponentLibs: Record<string, any>
TinyLowcodeComponent: Record<string, any>
}
}
interface ComponentConfig {
destructuring?: boolean
exportName?: string
}
interface ComponentDependency {
package?: string
script?: string
components: Record<string, string | ComponentConfig>
}
interface DynamicImportParams {
pkg: string
script?: string
}
export const addScript = (src: string, doc = document): Promise<unknown> => {
return new Promise((resolve, reject) => {
const script = doc.createElement('script')
script.setAttribute('type', 'text/javascript')
script.setAttribute('src', src)
script.async = false
script.onload = resolve
script.onerror = reject
doc.querySelector('head')!.appendChild(script)
})
}
export const addStyle = (href: string, doc = document): Promise<unknown> => {
return new Promise((resolve, reject) => {
const link = doc.createElement('link')
link.setAttribute('href', href)
link.setAttribute('rel', 'stylesheet')
link.onload = resolve
link.onerror = reject
doc.querySelector('head')!.appendChild(link)
})
}
export const copyObject = (node: any): any => {
if (typeof node === 'object') {
if (!node) {
return node
}
if (Array.isArray(node)) {
return node.map(copyObject)
}
const res: Record<string, any> = {}
Object.keys(node).forEach((key) => {
res[key] = copyObject(node[key])
})
const { componentName, id } = res as { componentName?: string; id?: string }
if (componentName && id) {
delete res.id
}
return res
}
return node
}
* 动态导入获取组件库模块
* @param {DynamicImportParams} param 模块参数,包含pkg模块名称和script模块的cdn地址
* @returns {Promise<any>} 返回组件库模块
*/
const dynamicImportComponentLib = async ({ pkg, script }: DynamicImportParams): Promise<any> => {
if (window.TinyComponentLibs[pkg]) {
return window.TinyComponentLibs[pkg]
}
if (!script) {
return {}
}
const href = window.parent.location.href || location.href
const scriptUrl = script.startsWith('.') ? new URL(script, href).href : script
if (!window.TinyComponentLibs[pkg]) {
const modules = await import( scriptUrl)
window.TinyComponentLibs[pkg] = modules
}
return window.TinyComponentLibs[pkg]
}
* 获取组件对象并缓存,组件渲染时使用
* @param {ComponentDependency} param 组件的依赖配置对象
* @returns {Promise<void>} 无返回值的Promise
*/
export const getComponents = async ({ package: pkg, script, components }: ComponentDependency): Promise<void> => {
if (!pkg) return
const modules = await dynamicImportComponentLib({ pkg, script })
Object.entries(components).forEach(([componentId, item]) => {
if (!window.TinyLowcodeComponent[componentId]) {
if (typeof item === 'string') {
window.TinyLowcodeComponent[componentId] = modules[item]
} else {
const config = item as ComponentConfig
window.TinyLowcodeComponent[componentId] =
config?.destructuring && config?.exportName ? modules[config.exportName] : modules?.default
}
}
})
}