Javascript 如何在React中缓存图像?
假设我有一个url列表,如下所示:Javascript 如何在React中缓存图像?,javascript,reactjs,caching,dom,Javascript,Reactjs,Caching,Dom,假设我有一个url列表,如下所示: ['/images/1'、'/images/2'、…] 我想预取其中的n,这样图像之间的转换会更快。我现在在组件willmount中执行的操作如下: componentWillMount() { const { props } = this; const { prefetchLimit = 1, document = dummyDocument, imgNodes } = props; const { images } =
['/images/1'、'/images/2'、…]
我想预取其中的n
,这样图像之间的转换会更快。我现在在组件willmount
中执行的操作如下:
componentWillMount() {
const { props } = this;
const { prefetchLimit = 1, document = dummyDocument, imgNodes } = props;
const { images } = document;
const toPrefecth = take(prefetchLimit, images);
const merged = zip(toPrefecth, imgNodes);
merged.forEach(([url, node]) => {
node.src = url;
});
}
将imgNodes
定义为:
imgNodes:times(=>newwindow.Image(),props.prefetchLimit),
和times
,zip
,以及take
来自
现在,当我在中使用这些URL时,会做出如下反应:
它根据Etag
和Expire
标记命中浏览器缓存,而不管url在何处使用。我还计划在视图内部点击n-1
时,使用它预取下一个n
图像,以相同的方式重用imgNodes
我的问题是:
- 这是一个有效的想法吗?给100多个组件使用这个想法,但一次只能看到1个
- 这样做会不会导致内存问题?我假设在卸载组件时,
将被垃圾收集imgNodes
redux
,因此我可以将这些图像保存在商店中,但这似乎是我在处理缓存,而不是利用浏览器的自然缓存
这主意有多糟糕?您不需要在所有组件中都这样做。一旦图像被下载,它就会被浏览器缓存,并且在所有组件中都可以访问,因此您只能在高级组件中的某个位置执行一次 我不知道您正试图通过缓存图像来创建什么样的用户体验,但是,您的代码只启动下载图像,但不知道图像是否正在下载、是否已成功下载甚至失败。因此,例如,您希望仅当图像已下载(为了使其平滑)时才显示更改图像的按钮或向组件添加类,您当前的代码可能会让您失望 你可能希望通过承诺来解决这个问题
// create an utility function somewhere
const checkImage = path =>
new Promise(resolve => {
const img = new Image()
img.onload = () => resolve(path)
img.onerror = () => reject()
img.src = path
})
...
// then in your component
class YourComponent extends Component {
this.state = { imagesLoaded: false }
componentDidMount = () =>
Promise.all(
R.take(limit, imgUrls).map(checkImage)
).then(() => this.setState(() => ({ imagesLoaded: true })),
() => console.error('could not load images'))
render = () =>
this.state.imagesLoaded
? <BeautifulComponent />
: <Skeleton />
}
//在某处创建一个实用函数
const checkImage=path=>
新承诺(解决=>{
常量img=新图像()
img.onload=()=>解析(路径)
img.onerror=()=>拒绝()
img.src=路径
})
...
//然后在组件中
类YourComponent扩展组件{
this.state={imagesLoaded:false}
componentDidMount=()=>
我保证(
R.take(限制,imgUrls).map(检查图像)
).然后(()=>这个.setState(()=>({imagesLoaded:true})),
()=>控制台。错误('无法加载图像')
渲染=()=>
这个.state.imagesLoaded
?
:
}
关于内存消耗,我认为不会发生任何不好的事情。浏览器通常会限制并行xhr请求的数量,因此您将无法创建一个巨大的堆使用峰值来崩溃任何东西,因为未使用的图像将被垃圾收集(但保留在浏览器缓存中)
Redux store是存储应用程序状态的地方,而不是应用程序资产,但无论如何,您将无法在那里存储任何实际图像。您是否使用了此功能?我有兴趣…@MathieuK。我们的结构/接口基本上与上述相同,利用了正常的HTTP缓存。因此您依赖浏览器/HTTP的默认行为?我依赖于我理解HTML的
img
规范的方式。这听起来像是说,一旦你请求浏览器获取资源,如果你再次请求,并且它在你的已知图像列表中,它就不必重新请求该资源。我希望如果我误解了这一点,浏览器/HTTP缓存会说不要重新蚀刻。