Ľub*_*mír 13 javascript reactjs
如何在React.js中预加载图像?我有下拉选择组件,其功能类似菜单,但我必须预先加载项目的图像图标,因为有时它们在首次打开时不可见.
我试过了:
https://github.com/sambernard/react-preload
https://github.com/wizardzloy/react-img-preload
第一个有很好的API易于理解和使用,但是是spaming控制台,警告图像没有加载,即使它们是.第二个有奇怪的API,但我尝试了示例,它没有预加载任何东西.
所以我可能需要自己实现一些东西,但不知道从哪里开始.或者另一种可能性是用webpack加载它们.
小智 25
假设你有pictures: string[];- 在你的组件的道具中定义的图片网址数组.您应该在组件中定义componentDidMount()方法,然后为要预加载的每个图片创建新的Image对象:
componentDidMount() {
this.props.pictures.forEach((picture) => {
const img = new Image();
img.src = picture.fileName;
});
}
Run Code Online (Sandbox Code Playgroud)
它强制浏览器加载所有图像.此示例使用TypeScript编写.
Jo *_* E. 17
TypeScript这是在组件内预加载图像的React Hooks(带有 )方式的半完整示例。您也可以将其作为钩子。
在这些示例中,我们在这里使用useEffectand useState,但实际的预加载工作是在preloadImage()我们拥有的函数内部。另请注意,导入图像时您将获得一个字符串。
直接添加到组件内部
import React, { useEffect, useState } from 'react'
import Image1 from 'images/image1.png'
import Image2 from 'images/image2.jpg'
import Image3 from 'images/image3.svg'
const preloadSrcList: string[] = [
Image1,
Image2,
Image3,
]
function preloadImage (src: string) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = function() {
resolve(img)
}
img.onerror = img.onabort = function() {
reject(src)
}
img.src = src
})
}
export default function Component() {
const [assetsLoaded, setAssetsLoaded] = useState<boolean>(false)
useEffect(() => {
let isCancelled = false
async function effect() {
if (isCancelled) {
return
}
const imagesPromiseList: Promise<any>[] = []
for (const i of preloadSrcList) {
imagesPromiseList.push(preloadImage(i))
}
await Promise.all(imagesPromiseList)
if (isCancelled) {
return
}
setAssetsLoaded(true)
}
effect()
return () => {
isCancelled = true
}
}, [])
if (!assetsLoaded) {
return <p>Preloading Assets</p>
}
return <p>Assets Finished Preloading</p>
}
Run Code Online (Sandbox Code Playgroud)
更好地作为钩子:useImagePreloader()
import { useEffect, useState } from 'react'
function preloadImage (src: string) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = function() {
resolve(img)
}
img.onerror = img.onabort = function() {
reject(src)
}
img.src = src
})
}
export default function useImagePreloader(imageList: string[]) {
const [imagesPreloaded, setImagesPreloaded] = useState<boolean>(false)
useEffect(() => {
let isCancelled = false
async function effect() {
console.log('PRELOAD')
if (isCancelled) {
return
}
const imagesPromiseList: Promise<any>[] = []
for (const i of imageList) {
imagesPromiseList.push(preloadImage(i))
}
await Promise.all(imagesPromiseList)
if (isCancelled) {
return
}
setImagesPreloaded(true)
}
effect()
return () => {
isCancelled = true
}
}, [imageList])
return { imagesPreloaded }
}
Run Code Online (Sandbox Code Playgroud)
在组件内使用 useImagePreloader()
import React, { useEffect, useState } from 'react'
import useImagePreloader from 'hooks/useImagePreloader'
import Image1 from 'images/image1.png'
import Image2 from 'images/image2.jpg'
import Image3 from 'images/image3.svg'
const preloadSrcList: string[] = [
Image1,
Image2,
Image3,
]
export default function Component() {
const { imagesPreloaded } = useImagePreloader(preloadSrcList)
if (!imagesPreloaded) {
return <p>Preloading Assets</p>
}
return <p>Assets Finished Preloading</p>
}
Run Code Online (Sandbox Code Playgroud)
小智 9
反应钩子方式
useEffect(() => {
//preloading image
faceArray.forEach((face) => {
const img = new Image();
img.src = face;
});
}, []);
Run Code Online (Sandbox Code Playgroud)
小智 6
如果您有一些图像在缓存后仍在重新加载,请尝试将它们存储在window对象中:
componentDidMount() {
const imagesPreload = [image1, image2, image3];
imagesPreload.forEach((image) => {
const newImage = new Image();
newImage.src = image;
window[image] = newImage;
});
}
Run Code Online (Sandbox Code Playgroud)
(您不需要从window对象调用图像)
重要的是将图像变量保存为 PERSISTANT。
在持久上下文中,在全局变量或在显示图像之前不会卸载的组件中:
window.preloadedPictures = []
Run Code Online (Sandbox Code Playgroud)
在我的组件中:
var preloadedData = pictures.map((picture) => {
const img = new Image();
img.src = picture.fileName;
return img
});
myContextOrGlobalVar.preloadedPictures = preloadedData ///IMPORTANT
Run Code Online (Sandbox Code Playgroud)
如果它只是提供一些小“图标” - (为什么不使用字体?) - 如果服务器提供 gzip 压缩的文件,您可以使用例如 base64。
否则,如果选择不是立即可见,您也可以将 img 标签(带有display: none)添加到之前的 HTML 中。另一种方法是将 Image 对象附加到 DOM 并.onload在显示组件之前等待(您提到的库使用这种方法)。
据我想象,webpack 或 React 不能为你做任何特别的事情。这是客户端的事情,这些只是实现你自己的预加载 API 的工具(甚至使用 JS/TS、React、Angular 等中现有的 API)
| 归档时间: |
|
| 查看次数: |
16356 次 |
| 最近记录: |