哇塞,有好吃的~

React实现组件缓存的一种思路

前言

  • 对于某个页面中的某个组件,很多时候需要其保持一直激活的状态,之前我的博客里面有一篇提到一种缓存策略,就是利用Routechildren方法来display该组件或隐藏该组件。但是这种方式需要借助到Route组件并且只能缓存整个页面,而不是页面中的部分组件。并且这种缓存单纯的只是在页面上把它的display变成了blocknone,仅仅是在路由离开的时候不卸载掉该组件。
  • 对此,还有一种思路也可以尝试一下,就是在一个组件离开前去保存它所有的state值,等到下次渲染组件的时候把上次卸载钱的state值还原回来,不就可以使得,组件重新渲染后依然是上一次离开前的状态吗。

实现思路

  • 给需要缓存的组件加一层高阶组件,在高阶组件中通过ref获取到该组件的实例。
  • ComponentDidMount中通过ref获取到的实例,调用组件的setState方法,把缓存的上一次的state数据注入进去。
  • ComponentWillUnmount中通过ref获取到的实例,去获取其所有state的值,并存在缓存中。

代码实现

const keepAlive = (Comp) => {

  let cache = {};

  return class Alive extends React.Component {

    componentDidMount() {
      const state = this.comp.state;
      this.comp.setState({ ...state, ...cache });
    }

    componentWillUnmount() {
      const state = this.comp.state;
      cache = { ...state };
    }

    render() {
      return (
        <Comp ref={comp => this.comp = comp} { ...this.props } />
      )
    }
  }
}
  • 使用
import React from 'react';
import keepAlive from 'keep-alive-react';

class Test extends React.Component {
  state = {
    count: 0
  }

  render() {
    const { count } = this.state;
    return (
      <div className="Test">
      Test
      <div>count: {count}</div>
      <div onClick={() => {
        this.setState({
          count: count + 1
        })
      }}>add</div>
    </div>
    );
  }
}

export default keepAlive(Test);

小结

  • 目前该实现方式,暂不能支持函数式组件,函数式组件的状态都是使用的hooks写法,而hooks写法中无法便捷统一的去获取其组件所有的state值,并且也无法针对函数式组件去拿到该组件内部的引用,导致该思路只能给继承自React.Component的组件使用。
  • 该方法已经发布到npm上。直接使用npm i keep-alive-react --save就可以像示例中一样进行全局引用。
posted @ 2020-09-03 16:57  风行者夜色  阅读(7121)  评论(0编辑  收藏  举报