Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在React中缓存图像?_Javascript_Reactjs_Caching_Dom - Fatal编程技术网

Javascript 如何在React中缓存图像?

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 } =

假设我有一个url列表,如下所示:

['/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缓存会说不要重新蚀刻。