当前位置: 移动技术网 > IT编程>开发语言>JavaScript > 自定义React-redux

自定义React-redux

2020年01月16日  | 移动技术网IT编程  | 我要评论

实现mini版react-redux

1. 理解react-redux模块

 1). react-redux模块整体是一个对象模块
 2). 包含2个重要属性: provider和connect
 3). provider
    值: 组件类
    作用: 向所有容器子组件提供全局store对象
    使用: <provider store={store}><xxx/></provider>
 4). connect
    值: 高阶函数
    作用: 包装组件生成容器组件, 让被包装组件能与redux进行通信
    使用: connect(mapstatetoprops, mapdispatchtoprops)(xxx)
 

2. context的理解和使用

1). 理解
  当你觉得多层传递props麻烦, 可以选择使用context
  context是组件对象的一个属性, 它的值是一个对象
  一个组件指定的context内数据, 所有层次子组件都可以读取到
  如果可以尽量不用context, 你可以选择使用react-redux, react-redux内部就利用了context
2). 使用
  父组件:
      static childcontexttypes = {
        color: proptypes.string
      }
      getchildcontext() {
        return {color: 'red'};
      }
  后代组件:
      static contexttypes = {
        color: proptypes.string
      }
      
      render () {
        this.context.color
      }

3. 实现代码: src/libs/react-redux/index.js

import react, {component} from 'react'
import proptypes from 'prop-types'

/*
1. provider组件类
 */
export class provider extends component {
  // 声明当前组件接收store
  static proptypes = {
    store: proptypes.object.isrequired
  }

  // 必须声明向子节点指定全局数据store
  static childcontexttypes = {
    store: proptypes.object.isrequired
  }

  // 指定向子组件指定全局数据store
  getchildcontext() {
    return {store: this.props.store};
  }

  render() {
    // 返回所有子节点(如果没有子节点返回undefined, 如果只有一个子节点它是对象, 如果有多个它是数组)
    return this.props.children
  }
}

/*
2. connect方法
 */
export function connect(mapstatetoprops = () => null, mapdispatchtoprops = {}) {
  // 返回函数(接收被包装组件类作为参数)
  return (wrapcomponent) => {
    // 返回一个新的组件类
    return class connectcomponent extends component {
      // 声明接收全局store
      static contexttypes = {
        store: proptypes.object.isrequired
      }

      // 构造函数的第2个参数为context对象
      constructor(props, context) {
        super(props)
        console.log('constructor', this.context) // 此时组件对象中还没有context
        // 从context中取出store
        const {store} = context
        // 一般属性: 调用mapstatetoprops函数得到包含所有需要传递一般属性的集合对象
        const stateprops = mapstatetoprops(store.getstate())
        // 分发action的函数属性: 调用自定义的整合函数生成包含多个分发action的函数的对象
        const dispatchprops = this.bindactioncreators(mapdispatchtoprops)

        // 初始化状态, 包含所有需要传递给wrapcomponent组件的一般属性
        this.state = {
          ...stateprops
        }
        // 将包含dispatch函数的对象保存在组件对象上(不用放到state中)
        this.dispatchprops = dispatchprops
      }

      /*
      根据包含多个action creator的对象, 返回一个包含多个分发action的函数的对象
       */
      bindactioncreators = (mapdispatchtoprops) => {
        // 准备一个保存分发action函数的对象容器
        const dispatchprops = {}
        // 遍历每个action creator
        object.keys(mapdispatchtoprops).foreach((key) => {
          // 得到某个action creator
          const actioncreator = mapdispatchtoprops[key]
          //定义包含分发action代码的函数, 并只在到准备好的容器中
          dispatchprops[key] = (...args) => {
            this.context.store.dispatch(actioncreator(...args))
          }
        })
        // 返回dispatch代码函数容器对象
        return dispatchprops
      }

      componentdidmount() {
        console.log('componentdidmount', this.constructor)
        // 得到store
        const {store} = this.context
        // 订阅监听
        store.subscribe(() => {
          // 一旦store中的state有变化, 更新组件状态, 从而导致被包装组件重新渲染
          this.setstate(mapstatetoprops(store.getstate()))
        })
      }

      render() {
        return <wrapcomponent {...this.state} {...this.dispatchprops} />
      }
    }
  }
}

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网