如何在React中缓存图像?

Tim*_*rts 5 javascript dom caching reactjs

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

[ '/images/1', '/images/2', ... ]

我想预取n那些,以便在图像之间转换更快.我现在正在做的componentWillMount是以下内容:

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;
      });
    }
Run Code Online (Sandbox Code Playgroud)

imgNodes像这样被定义:

imgNodes: times(_ => new window.Image(), props.prefetchLimit),

并且times,ziptake来自何处ramda.

现在当我使用那些内部的url反应时:

<img src={url} />

无论网址在何处使用,它都会根据EtagExpire标签访问浏览器缓存.n每当我们点击n - 1视图内部时,我也计划使用它来预取下一个图像,imgNodes并以相同的方式重复使用.

我的问题是:

  • 这甚至是一个有效的想法,给出100多个将使用这个想法的组件,但一次只能看到1个?

  • 这样做会遇到内存问题吗?我假设imgNodes在卸载组件时将收集垃圾.

我们正在使用,redux所以我可以将这些图像保存在商店中,但这似乎是我正在处理缓存而不是利用浏览器的自然缓存.

这个想法有多糟糕?

deh*_*zer 7

您无需在所有组件中执行此操作.一旦下载了图像,它就会被浏览器缓存,并且可以在所有组件中访问,因此您只能在高级组件中的某个位置执行此操作.

我不知道你试图通过缓存图像创建什么样的UX,但是,你的代码只会启动下载图像,但不知道图像是否正在下载,是否已成功下载甚至失败.因此,例如,您想要显示一个按钮来更改图像或仅在下载图像时将类添加到组件(为了使图像平滑),您当前的代码可能会让您失望.

您可能希望使用Promises解决此问题.

// 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 />
}
Run Code Online (Sandbox Code Playgroud)

关于内存消耗 - 我认为不会发生任何不好的事情.浏览器通常会限制并行xhr请求的数量,因此您将无法创建巨大的堆使用峰值来崩溃任何内容,因为未使用的图像将被垃圾收集(但仍保留在浏览器缓存中).

Redux商店是存储应用程序状态的地方,而不是应用程序资产,但无论如何,您将无法存储任何实际图像.