Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | 22x 22x 10x 10x 10x 10x 10x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 1x 1x 1x 1x 1x 5x 5x 5x 5x 22x 21x 22x 22x 3x 1x 2x 22x 17x 18x 21x 18x 21x 21x 21x | export type LoadResourceElement = | HTMLScriptElement | HTMLLinkElement | HTMLStyleElement | HTMLImageElement /** * 资源类型。 * * @public */ export enum LoadResourceUrlType { /** 样式资源 */ css = 'css', /** 样式文本 */ cssText = 'cssText', /** 代码资源 */ js = 'js', /** 代码文本 */ jsText = 'jsText', /** 图片资源 */ img = 'img', } export type LoadResourceHook = (el: LoadResourceElement) => any /** * 资源地址。 * * @public */ export interface LoadResourceUrl { /** 资源类型 */ type: LoadResourceUrlType /** 资源路径 */ path: string /** 备用资源路径 */ alternatePath?: string /** 钩子 */ hook?: LoadResourceHook } export interface LoadResourceOptions { /** 钩子 */ hook?: LoadResourceHook } function loadSpecificResource( url: LoadResourceUrl, ): Promise<LoadResourceElement> { return new Promise((resolve, reject) => { let el!: LoadResourceElement switch (url.type) { case LoadResourceUrlType.js: { const _el = document.createElement('script') _el.src = url.path _el.async = true el = _el } break case LoadResourceUrlType.jsText: { const _el = document.createElement('script') _el.setAttribute('type', 'text/javascript') _el.textContent = url.path el = _el } break case LoadResourceUrlType.css: { const _el = document.createElement('link') _el.rel = 'stylesheet' _el.href = url.path el = _el } break case LoadResourceUrlType.cssText: { const _el = document.createElement('style') _el.setAttribute('type', 'text/css') _el.textContent = url.path el = _el } break case LoadResourceUrlType.img: { const _el = document.createElement('img') _el.src = url.path el = _el } break /* istanbul ignore next */ default: break } if (url.hook) { url.hook(el) } el.onload = () => resolve(el) el.onerror = () => { if (url.alternatePath) { loadSpecificResource({ type: url.type, path: url.alternatePath, }).then(resolve, reject) } else { reject(el) } } if (url.type !== LoadResourceUrlType.img) { document.head.appendChild(el) } }) } /** * 加载图片、代码、样式等资源。 * * @public * @param url 要加载的资源地址 * @param options 选项 * @returns 返回各资源的 HTML 元素组成的数组 * @example * ```typescript * loadResource([ * 'https://foo.bar/all.js', * 'https://foo.bar/all.css', * 'https://foo.bar/logo.png', * { * type: LoadResourceUrlType.js, * path: 'https://s1.foo.bar/js/full', * alternatePath: 'https://s2.foo.bar/js/full', * }, * ]).then(() => { * // 资源加载完成后的操作 * }) * ``` */ export function loadResource( url: string | LoadResourceUrl | Array<string | LoadResourceUrl>, options?: LoadResourceOptions, ): Promise<Array<LoadResourceElement>> { const urls = (Array.isArray(url) ? url : [url]).map<LoadResourceUrl>(item => { return !(typeof item === 'string') ? item : { type: /\.css$/i.test(item) ? LoadResourceUrlType.css : /\.(png|jpg|jpeg|gif|svg)$/i.test(item) ? LoadResourceUrlType.img : LoadResourceUrlType.js, path: item, } }) return Promise.all( urls.map(url => loadSpecificResource({ ...url, hook: el => { options?.hook?.(el) url.hook?.(el) }, }), ), ) } |