前端函数式演进
上QQ阅读APP看书,第一时间看更新

2.4.1 闭包和单例

在2.1.1节我们用闭包实现了单例。单例是前端开发经常用到的模式,前端使用单例实现React等框架中的全局变量和服务,如代码清单2-9所示。

代码清单2-9 闭包和单例实现彩蛋功能


// 1  使用单例服务的全局变量展示彩蛋数量
// services/config.js
const Singleton = function(easterEggsCount) {
  this.storeEasterEggsCount = easterEggsCount;
}

Singleton.getInstanceEasterEggsCount = (function(){
  var instance;
  return function() {
    if (!instance) {
      instance = new Singleton(1);
    } else {
      instance.storeEasterEggsCount += 1;
    }
    return instance.storeEasterEggsCount;
  }
})();

global.constants = {
  getEasterEggsInstatnce: Singleton.getInstanceEasterEggsCount()
  appname: 'breakthrough',
};

// 调用彩蛋功能方法,省略业务逻辑
// pages/overview/OverviewEvaluation.js
import React from 'react'
import '@/services/config';

class OverviewEvaluation extends React.Component {
  render() {
    return (
      <div className="over-view-e-page">
        { global.constants.getEasterEggsInstatnce }
      </div>
    )
  }
}

export default OverviewEvaluation

// 2 使用React支持的Context完成类似功能
// pages/easterEggs/EasterEggsCountContext.js
import React, { createContext } from 'react'
const EasterEggsCountContext = createContext();

export default EasterEggsCountContext;

// 外层代码,生成全局数据
// pages/OverviewPage.js
import React, { createContext } from 'react'
import EasterEggsCountContext from './easterEggs'
// 省略业务代码

class OverviewPage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      easterEggsCount: 0
    }
    this.increaseEasterEggsCount = this.increaseEasterEggsCount.bind(this)
  }

  increaseEasterEggsCount() {
    if (100 * Math.random() > 95) {
      this.setState({
        easterEggsCount: _easterEggsCount + 1
      })
    }
  }

  render() {
    const _easterEggsCount = this.state.easterEggsCount
    return (
      <EasterEggsCountContext.Provider value={ _easterEggsCount }>
        <div className="over-view-page"
             onClick={this.increaseEasterEggsCount}>
          // 省略业务代码
      </EasterEggsCountContext.Provider>
    )
  }
}
export default OverviewPage

// 子组件,使用全局数据
// pages/overview/OverviewLink.js
import React from 'react'
import EasterEggsCountContext from '../easterEggs'

class OverviewLink extends React.Component {
  render() {
    return (
      <EasterEggsCountContext.Customer>
        {
          easterEggsCount => (
            <div className="over-view-l-page">
              { easterEggsCount }
            </div>
          )
        }
      </EasterEggsCountContext.Customer>
    )
  }
}

export default OverviewLink