feat(图片缓存功能): 优化缓存策略,实现全部目标图片的缓存存取,解决了之前部分图片依旧从网络中获取的问题,以及assets图片没有缓存的问题
This commit is contained in:
parent
bccabf6426
commit
e3fdd3959d
@ -1,57 +1,138 @@
|
||||
// src/directives/smartImage.js
|
||||
import { imageCacheManager } from '@/utils/imageCacheManager'
|
||||
import { nextTick } from 'vue'
|
||||
|
||||
export const smartImage = {
|
||||
async mounted(el, binding) {
|
||||
// 只有当绑定的值存在时才处理
|
||||
if (binding.value) {
|
||||
// 设置加载状态样式
|
||||
el.style.opacity = '0'
|
||||
el.style.transition = 'opacity 0.3s ease-in-out'
|
||||
// 设置加载状态样式
|
||||
el.style.opacity = '0'
|
||||
el.style.transition = 'opacity 0.3s ease-in-out'
|
||||
|
||||
// 等待DOM更新确保样式生效
|
||||
await nextTick()
|
||||
// 获取 URL:优先使用 binding.value,如果为空则尝试从元素获取
|
||||
const url = getValidUrl(binding.value, el)
|
||||
|
||||
try {
|
||||
// 统一使用缓存管理器处理所有可缓存资源
|
||||
if (imageCacheManager.isBuildAsset(binding.value)) {
|
||||
await imageCacheManager.loadImage(binding.value)
|
||||
el.src = binding.value
|
||||
el.style.opacity = '1'
|
||||
} else {
|
||||
// 外部链接直接加载
|
||||
el.src = binding.value
|
||||
el.style.opacity = '1'
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`图片加载失败: ${binding.value}`, error)
|
||||
el.src = binding.value
|
||||
el.style.opacity = '1'
|
||||
}
|
||||
if (url) {
|
||||
await processImage(el, url)
|
||||
|
||||
// 保存当前处理的 URL,用于后续比较
|
||||
el._smartImageCurrentUrl = url
|
||||
// 保存原始绑定值
|
||||
el._smartImageOriginalBindingValue = binding.value
|
||||
} else {
|
||||
// 如果 URL 无效,恢复透明度
|
||||
el.style.opacity = '1'
|
||||
}
|
||||
},
|
||||
|
||||
async updated(el, binding) {
|
||||
if (binding.value !== binding.oldValue && binding.value) {
|
||||
el.style.opacity = '0'
|
||||
// 获取当前有效的 URL
|
||||
const currentUrl = getValidUrl(binding.value, el)
|
||||
|
||||
// 等待DOM更新确保样式生效
|
||||
await nextTick()
|
||||
// 检查是否真的需要更新
|
||||
// 1. binding.value 发生了变化
|
||||
// 2. 或者元素的 src 属性发生了变化
|
||||
const bindingChanged = binding.value !== binding.oldValue
|
||||
const elementSrcChanged = currentUrl && currentUrl !== el._smartImageCurrentUrl
|
||||
|
||||
try {
|
||||
if (imageCacheManager.isBuildAsset(binding.value)) {
|
||||
await imageCacheManager.loadImage(binding.value)
|
||||
el.src = binding.value
|
||||
el.style.opacity = '1'
|
||||
} else {
|
||||
el.src = binding.value
|
||||
el.style.opacity = '1'
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`图片更新失败: ${binding.value}`, error)
|
||||
el.src = binding.value
|
||||
el.style.opacity = '1'
|
||||
if (bindingChanged || elementSrcChanged) {
|
||||
if (currentUrl && currentUrl !== el._smartImageCurrentUrl) {
|
||||
// 设置加载状态
|
||||
el.style.opacity = '0'
|
||||
await processImage(el, currentUrl)
|
||||
el._smartImageCurrentUrl = currentUrl
|
||||
el._smartImageOriginalBindingValue = binding.value
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 清理函数
|
||||
unmounted(el) {
|
||||
// 清理可能的事件监听器
|
||||
el.removeEventListener('load', el._smartImageLoadHandler)
|
||||
el.removeEventListener('error', el._smartImageErrorHandler)
|
||||
// 清理保存的引用
|
||||
delete el._smartImageCurrentUrl
|
||||
delete el._smartImageOriginalBindingValue
|
||||
delete el._smartImageLoadHandler
|
||||
delete el._smartImageErrorHandler
|
||||
},
|
||||
}
|
||||
|
||||
// 获取有效的 URL
|
||||
function getValidUrl(bindingValue, el) {
|
||||
// 优先级:1. binding.value 2. el.getAttribute('src') 3. el.src
|
||||
const candidates = [bindingValue, el.getAttribute('src'), el.src]
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (
|
||||
candidate &&
|
||||
candidate !== 'null' &&
|
||||
candidate !== 'undefined' &&
|
||||
!candidate.includes('blob:') &&
|
||||
typeof candidate === 'string'
|
||||
) {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// 将图片处理逻辑提取为单独函数
|
||||
async function processImage(el, url) {
|
||||
if (!url) {
|
||||
return
|
||||
}
|
||||
|
||||
await nextTick()
|
||||
|
||||
try {
|
||||
// 统一使用缓存管理器处理所有可缓存资源
|
||||
if (imageCacheManager.isBuildAsset(url)) {
|
||||
// 获取缓存的图片 URL(如果是缓存的图片会返回 blob URL,否则返回原始 URL)
|
||||
const imageUrl = await imageCacheManager.getCacheImageUrl(url)
|
||||
|
||||
// 设置加载完成的回调
|
||||
const handleLoad = () => {
|
||||
el.style.opacity = '1'
|
||||
el.removeEventListener('load', handleLoad)
|
||||
}
|
||||
el.addEventListener('load', handleLoad)
|
||||
el._smartImageLoadHandler = handleLoad // 保存引用以便清理
|
||||
|
||||
// 设置错误处理回调
|
||||
const handleError = (error) => {
|
||||
console.error(`图片加载失败:`, url, error)
|
||||
el.style.opacity = '1'
|
||||
el.removeEventListener('error', handleError)
|
||||
}
|
||||
el.addEventListener('error', handleError)
|
||||
el._smartImageErrorHandler = handleError // 保存引用以便清理
|
||||
|
||||
// 设置图片源
|
||||
el.src = imageUrl
|
||||
} else {
|
||||
// 外部链接直接加载
|
||||
const handleLoad = () => {
|
||||
el.style.opacity = '1'
|
||||
el.removeEventListener('load', handleLoad)
|
||||
}
|
||||
el.addEventListener('load', handleLoad)
|
||||
el._smartImageLoadHandler = handleLoad
|
||||
|
||||
const handleError = (error) => {
|
||||
// console.error(`外部图片加载失败:`, url, error)
|
||||
el.style.opacity = '1'
|
||||
el.removeEventListener('error', handleError)
|
||||
}
|
||||
el.addEventListener('error', handleError)
|
||||
el._smartImageErrorHandler = handleError
|
||||
|
||||
el.src = url
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`图片处理失败: ${url}`, error)
|
||||
el.src = url
|
||||
el.style.opacity = '1'
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,15 +15,28 @@ class ImageCacheManager {
|
||||
this.init()
|
||||
}
|
||||
|
||||
// 根据资源类型选择缓存
|
||||
async getCacheForUrl(url) {
|
||||
// 规范化 URL
|
||||
const normalizedUrl = this.normalizeUrl(url)
|
||||
|
||||
let cacheName
|
||||
if (
|
||||
url.startsWith('https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5') ||
|
||||
url.startsWith('/oss/h5/')
|
||||
normalizedUrl.startsWith('https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5') ||
|
||||
normalizedUrl.includes('/oss/h5/')
|
||||
) {
|
||||
return await caches.open(this.imageCacheName)
|
||||
cacheName = this.imageCacheName
|
||||
} else if (normalizedUrl.includes('/assets/')) {
|
||||
cacheName = this.assetCacheName
|
||||
} else {
|
||||
return await caches.open(this.assetCacheName)
|
||||
// 其他外部链接放入通用图片缓存
|
||||
cacheName = this.imageCacheName
|
||||
}
|
||||
|
||||
try {
|
||||
return await caches.open(cacheName)
|
||||
} catch (error) {
|
||||
console.error(`打开缓存失败: ${cacheName}`, error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +68,6 @@ class ImageCacheManager {
|
||||
|
||||
// 等待所有清除操作完成
|
||||
await Promise.all(cachesToClear.map((name) => caches.delete(name)))
|
||||
console.log(`已清理${clearType}类型缓存:`, cachesToClear)
|
||||
} catch (error) {
|
||||
console.warn('清理缓存失败:', error)
|
||||
}
|
||||
@ -71,12 +83,10 @@ class ImageCacheManager {
|
||||
|
||||
if (!cachedVersion) {
|
||||
localStorage.setItem(this.cacheVersionKey, this.currentAppVersion)
|
||||
console.log('初始化图片缓存版本:', this.currentAppVersion)
|
||||
return
|
||||
}
|
||||
|
||||
if (cachedVersion !== this.currentAppVersion) {
|
||||
console.log(`图片缓存版本更新: ${cachedVersion} -> ${this.currentAppVersion}`)
|
||||
await this.clearOldCaches()
|
||||
localStorage.setItem(this.cacheVersionKey, this.currentAppVersion)
|
||||
}
|
||||
@ -164,7 +174,6 @@ class ImageCacheManager {
|
||||
// 执行删除操作
|
||||
for (const key of itemsToDelete) {
|
||||
await cache.delete(key)
|
||||
console.log(`已删除超出限制的缓存项: ${key.url}`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('检查缓存限制时出错:', error)
|
||||
@ -182,57 +191,53 @@ class ImageCacheManager {
|
||||
)
|
||||
|
||||
await Promise.all(oldCaches.map((name) => caches.delete(name)))
|
||||
console.log('已清理旧版本图片缓存:', oldCaches)
|
||||
} catch (error) {
|
||||
console.warn('清理旧图片缓存失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
//判断是否为适合缓存资源
|
||||
// 判断是否为适合缓存资源
|
||||
isBuildAsset(url) {
|
||||
try {
|
||||
// 如果是相对路径,肯定是本地资源
|
||||
if (url.startsWith('/') || url.startsWith('./') || url.startsWith('../')) {
|
||||
return true
|
||||
}
|
||||
// 规范化 URL
|
||||
const normalizedUrl = this.normalizeUrl(url)
|
||||
|
||||
// 如果是绝对URL,检查是否为本地域名
|
||||
const currentOrigin = window.location.origin
|
||||
if (url.startsWith(currentOrigin)) {
|
||||
return true
|
||||
}
|
||||
const containsAssets = normalizedUrl.includes('/assets/')
|
||||
const containsOssH5 = normalizedUrl.includes('/oss/h5/')
|
||||
const startsWithOss = normalizedUrl.startsWith(
|
||||
'https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5/'
|
||||
)
|
||||
|
||||
// 检查是否为构建后的资源(包含哈希)
|
||||
if (/\.[a-f0-9]{8,}\./.test(url)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 检查是否为本地assets路径
|
||||
if (url.includes('/src/assets/') || url.includes('/assets/')) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 允许缓存特定域名下的资源
|
||||
const ossBaseUrl = 'https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5'
|
||||
|
||||
if (url.startsWith(ossBaseUrl)) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
// 只缓存三种类型的资源
|
||||
return containsAssets || containsOssH5 || startsWithOss
|
||||
} catch (error) {
|
||||
console.warn('判断资源类型时出错:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 分离缓存图片
|
||||
// 规范化 URL 以确保一致性
|
||||
normalizeUrl(url) {
|
||||
try {
|
||||
// 如果是相对路径,转换为完整 URL 进行匹配
|
||||
if (url.startsWith('/')) {
|
||||
return new URL(url, window.location.origin).toString()
|
||||
}
|
||||
// 如果已经是完整 URL,直接返回
|
||||
return new URL(url).toString()
|
||||
} catch (e) {
|
||||
// 如果 URL 格式不正确,返回原 URL
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存图片
|
||||
async cacheImage(url) {
|
||||
if (!('caches' in window) || !url) return
|
||||
|
||||
try {
|
||||
if (this.isBuildAsset(url)) {
|
||||
const cache = await this.getCacheForUrl(url) // 使用分离的缓存
|
||||
const cache = await this.getCacheForUrl(url)
|
||||
const cachedResponse = await cache.match(url)
|
||||
|
||||
if (!cachedResponse) {
|
||||
@ -248,8 +253,6 @@ class ImageCacheManager {
|
||||
})
|
||||
if (response.ok) {
|
||||
await cache.put(url, response.clone())
|
||||
console.log(`图片已缓存: ${url}`)
|
||||
|
||||
// 添加新图片后立即检查并强制执行限制
|
||||
await this.enforceCacheLimits(cache)
|
||||
}
|
||||
@ -260,15 +263,94 @@ class ImageCacheManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取缓存的图片 Blob URL
|
||||
async getCacheImageUrl(url) {
|
||||
if (!('caches' in window)) return url
|
||||
|
||||
try {
|
||||
// 规范化 URL
|
||||
const normalizedUrl = this.normalizeUrl(url)
|
||||
|
||||
if (this.isBuildAsset(normalizedUrl)) {
|
||||
const cache = await this.getCacheForUrl(normalizedUrl)
|
||||
|
||||
// 尝试多种匹配方式以确保找到缓存的图片
|
||||
// 1. 首先尝试使用 Request 对象进行精确匹配
|
||||
const request = new Request(normalizedUrl, {
|
||||
mode: 'cors',
|
||||
credentials: 'omit',
|
||||
})
|
||||
let cachedResponse = await cache.match(request)
|
||||
|
||||
if (!cachedResponse) {
|
||||
// 2. 如果精确匹配失败,尝试直接使用 URL 字符串匹配
|
||||
cachedResponse = await cache.match(normalizedUrl)
|
||||
}
|
||||
|
||||
if (!cachedResponse) {
|
||||
// 3. 如果还是没找到,尝试使用 URL 的 origin + pathname(去掉查询参数)
|
||||
const urlObj = new URL(normalizedUrl)
|
||||
const urlWithoutQuery = `${urlObj.origin}${urlObj.pathname}`
|
||||
cachedResponse = await cache.match(urlWithoutQuery)
|
||||
}
|
||||
|
||||
if (!cachedResponse) {
|
||||
// 4. 尝试匹配去掉协议的 URL
|
||||
const urlWithoutProtocol = normalizedUrl.replace(/^https?:\/\//, '')
|
||||
cachedResponse = await cache.match(urlWithoutProtocol)
|
||||
}
|
||||
|
||||
if (cachedResponse) {
|
||||
const blob = await cachedResponse.blob()
|
||||
return URL.createObjectURL(blob)
|
||||
} else {
|
||||
// 缓存未命中,触发预缓存
|
||||
try {
|
||||
await this.cacheImage(normalizedUrl)
|
||||
} catch (cacheError) {
|
||||
console.warn(`预缓存失败: ${cacheError}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果没有缓存,返回原始 URL
|
||||
return url
|
||||
} catch (error) {
|
||||
console.warn('获取缓存图片 URL 失败:', error)
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
// 从缓存获取图片
|
||||
async getCachedImage(url) {
|
||||
if (!('caches' in window)) return null
|
||||
|
||||
try {
|
||||
// 规范化 URL
|
||||
const normalizedUrl = this.normalizeUrl(url)
|
||||
|
||||
// 只从缓存获取本地资源
|
||||
if (this.isBuildAsset(url)) {
|
||||
const cache = await this.getCacheForUrl(url) // 使用相同的逻辑选择缓存
|
||||
return await cache.match(url)
|
||||
if (this.isBuildAsset(normalizedUrl)) {
|
||||
const cache = await this.getCacheForUrl(normalizedUrl) // 使用相同的逻辑选择缓存
|
||||
|
||||
// 尝试多种匹配方式
|
||||
let cachedResponse = await cache.match(
|
||||
new Request(normalizedUrl, {
|
||||
mode: 'cors',
|
||||
credentials: 'omit',
|
||||
})
|
||||
)
|
||||
|
||||
if (!cachedResponse) {
|
||||
cachedResponse = await cache.match(normalizedUrl)
|
||||
}
|
||||
|
||||
if (!cachedResponse) {
|
||||
const urlObj = new URL(normalizedUrl)
|
||||
const urlWithoutQuery = `${urlObj.origin}${urlObj.pathname}`
|
||||
cachedResponse = await cache.match(urlWithoutQuery)
|
||||
}
|
||||
|
||||
return cachedResponse
|
||||
}
|
||||
return null
|
||||
} catch (error) {
|
||||
@ -279,17 +361,20 @@ class ImageCacheManager {
|
||||
|
||||
// 智能加载图片
|
||||
async loadImage(src) {
|
||||
// 规范化 URL
|
||||
const normalizedSrc = this.normalizeUrl(src)
|
||||
|
||||
// 1. 请求去重:检查是否有相同请求正在进行
|
||||
if (this.pendingRequests.has(src)) {
|
||||
if (this.pendingRequests.has(normalizedSrc)) {
|
||||
// 返回现有的Promise,避免重复请求
|
||||
return this.pendingRequests.get(src)
|
||||
return this.pendingRequests.get(normalizedSrc)
|
||||
}
|
||||
|
||||
// 2. 创建新的加载Promise
|
||||
const loadPromise = new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
// 3. 尝试从缓存获取
|
||||
const cachedResponse = await this.getCachedImage(src)
|
||||
const cachedResponse = await this.getCachedImage(normalizedSrc)
|
||||
if (cachedResponse) {
|
||||
// 4. 缓存命中,处理图片
|
||||
const blob = await cachedResponse.blob()
|
||||
@ -308,7 +393,7 @@ class ImageCacheManager {
|
||||
// 8. 清理临时URL
|
||||
URL.revokeObjectURL(imageUrl)
|
||||
// 9. 回退到网络加载
|
||||
this.loadImageFromNetwork(src, resolve, reject)
|
||||
this.loadImageFromNetwork(normalizedSrc, resolve, reject)
|
||||
}
|
||||
|
||||
img.src = imageUrl // 10. 开始加载
|
||||
@ -316,67 +401,86 @@ class ImageCacheManager {
|
||||
}
|
||||
|
||||
// 11. 缓存中没有或不是本地资源,从网络加载
|
||||
this.loadImageFromNetwork(src, resolve, reject)
|
||||
this.loadImageFromNetwork(normalizedSrc, resolve, reject)
|
||||
} catch (error) {
|
||||
this.loadImageFromNetwork(src, resolve, reject)
|
||||
this.loadImageFromNetwork(normalizedSrc, resolve, reject)
|
||||
}
|
||||
})
|
||||
|
||||
// 12. 记录正在进行的请求
|
||||
this.pendingRequests.set(src, loadPromise)
|
||||
this.pendingRequests.set(normalizedSrc, loadPromise)
|
||||
|
||||
try {
|
||||
const result = await loadPromise
|
||||
return result
|
||||
} finally {
|
||||
// 13. 清理记录
|
||||
this.pendingRequests.delete(src)
|
||||
this.pendingRequests.delete(normalizedSrc)
|
||||
}
|
||||
}
|
||||
|
||||
// 从网络加载图片
|
||||
async loadImageFromNetwork(src, resolve, reject) {
|
||||
try {
|
||||
// 规范化 URL
|
||||
const normalizedSrc = this.normalizeUrl(src)
|
||||
|
||||
// 统一处理所有资源,不再对OSS做特殊处理
|
||||
const response = await fetch(src, {
|
||||
const response = await fetch(normalizedSrc, {
|
||||
mode: 'cors',
|
||||
credentials: 'omit',
|
||||
cache: 'no-store', // 强制不使用 HTTP 缓存
|
||||
headers: {
|
||||
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
||||
Pragma: 'no-cache',
|
||||
Expires: '0',
|
||||
},
|
||||
})
|
||||
|
||||
if (response.ok) {
|
||||
const img = new Image()
|
||||
img.onload = async () => {
|
||||
console.log(`[ImageCacheManager] 图片加载成功: ${src}`)
|
||||
resolve(img)
|
||||
// 缓存响应
|
||||
if (this.isBuildAsset(src)) {
|
||||
try {
|
||||
await this.cacheImage(src) // 使用标准缓存方法
|
||||
} catch (cacheError) {
|
||||
console.warn('缓存图片时出错:', cacheError)
|
||||
}
|
||||
// 克隆响应,一份用于缓存,一份用于图片加载
|
||||
const isAsset = this.isBuildAsset(normalizedSrc)
|
||||
const responseForCache = isAsset ? response.clone() : null
|
||||
const responseForImage = response // 原始响应用于图片加载
|
||||
|
||||
// 先缓存响应
|
||||
if (isAsset) {
|
||||
try {
|
||||
// 使用 getCacheForUrl 确保使用正确的缓存
|
||||
const cache = await this.getCacheForUrl(normalizedSrc)
|
||||
await cache.put(normalizedSrc, responseForCache) // 使用克隆的响应进行缓存
|
||||
} catch (cacheError) {
|
||||
console.warn('缓存图片时出错:', cacheError)
|
||||
}
|
||||
}
|
||||
|
||||
const img = new Image()
|
||||
img.onload = () => {
|
||||
resolve(img)
|
||||
}
|
||||
img.onerror = (error) => {
|
||||
console.warn(`[ImageCacheManager] 图片 onload 失败: ${src}`, error)
|
||||
reject(error)
|
||||
}
|
||||
img.src = URL.createObjectURL(await response.blob())
|
||||
img.src = URL.createObjectURL(await responseForImage.blob()) // 使用原始响应
|
||||
} else {
|
||||
reject(new Error(`HTTP ${response.status}`))
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('网络加载图片失败:', src, error)
|
||||
reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
// 添加辅助方法来获取缓存名称
|
||||
getCacheNameByUrl(url) {
|
||||
const normalizedUrl = this.normalizeUrl(url)
|
||||
|
||||
if (
|
||||
normalizedUrl.startsWith('https://tkm-likei.oss-ap-southeast-1.aliyuncs.com/h5') ||
|
||||
normalizedUrl.includes('/oss/h5/')
|
||||
) {
|
||||
return this.imageCacheName
|
||||
} else if (normalizedUrl.includes('/assets/')) {
|
||||
return this.assetCacheName
|
||||
} else {
|
||||
return this.imageCacheName
|
||||
}
|
||||
}
|
||||
|
||||
// 为OSS图片创建缓存的特殊处理
|
||||
async cacheImageFromImage(src, img) {
|
||||
try {
|
||||
@ -406,7 +510,6 @@ class ImageCacheManager {
|
||||
})
|
||||
// 将图片存入缓存
|
||||
await cache.put(src, response.clone())
|
||||
console.log(`OSS图片已缓存: ${src}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// src/utils/imagePreloader.js
|
||||
import { imageCacheManager } from '@/utils/imageCacheManager'
|
||||
|
||||
export const preloadImages = (sources) => {
|
||||
export const preloadImages = async (sources) => {
|
||||
let urls = []
|
||||
|
||||
// 支持数组和对象形式的图片源
|
||||
@ -11,15 +11,27 @@ export const preloadImages = (sources) => {
|
||||
urls = Object.values(sources)
|
||||
}
|
||||
|
||||
// 使用 SmartImage 缓存系统
|
||||
urls.forEach((url) => {
|
||||
// 创建预加载 Promise 数组
|
||||
const preloadPromises = urls.map((url) => {
|
||||
if (imageCacheManager.isBuildAsset(url)) {
|
||||
imageCacheManager.loadImage(url) // 触发缓存加载
|
||||
// 对于可缓存的图片,使用 loadImage 方法
|
||||
return imageCacheManager.loadImage(url)
|
||||
} else {
|
||||
const img = new Image()
|
||||
img.src = url
|
||||
// 对于外部链接,创建一个 Promise 来加载图片
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
img.onload = () => resolve(img)
|
||||
img.onerror = (error) => reject(error)
|
||||
img.src = url
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
console.log(`开始预加载 ${urls.length} 张图片`)
|
||||
// 等待所有预加载完成
|
||||
try {
|
||||
await Promise.all(preloadPromises)
|
||||
} catch (error) {
|
||||
console.error('预加载图片失败:', error)
|
||||
throw error // 重新抛出错误,让调用方可以处理
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user