web前端:自定义React-redux

    作者:路飞910 更新于: 2020-03-30 20:14:50

    Web开发

      React起源于Facebook的内部项目,因为该公司对市场上所有JavaScriptMVC框架,都不满意,就决定自己写一套,用来架设Instagram的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。

      React主要用于构建UI。你可以在React里传递多种类型的参数,如声明代码,帮助你渲染出UI、也可以是静态的HTMLDOM元素、也可以传递动态变量、甚至是可交互的应用组件。

      实现mini版react-redux

      1.理解react-redux模块

      1).react-redux模块整体是一个对象模块

      2).包含2个重要属性:Provider和connect

      3).Provider

      值:组件类

      作用:向所有容器子组件提供全局store对象

      使用:

      4).connect

      值:高阶函数

      作用:包装组件生成容器组件,让被包装组件能与redux进行通信

      使用:connect(mapStateToProPS,mapDispatchToProps)(Xxx)

      2.context的理解和使用

      1).理解

      当你觉得多层传递props麻烦,可以选择使用context

      context是组件对象的一个属性,它的值是一个对象

      一个组件指定的context内数据,所有层次子组件都可以读取到

      如果可以尽量不用context,你可以选择使用react-redux,react-redux内部就利用了context

      2).使用

      父组件:

      staticchildContextTypes={

      color:PropTypes.string

      }

      getChildContext(){

      return{color:'red'};

      }

      后代组件:

      staticcontextTypes={

      color:PropTypes.string

      }

      render(){

      this.context.color

      }

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

      importReact,{Component}from'react'

      importPropTypesfrom'prop-types'

      /*

      1.Provider组件类

      */

      exportclassProviderextendsComponent{

      //声明当前组件接收store

      staticpropTypes={

      store:PropTypes.object.isRequired

      }

      //必须声明向子节点指定全局数据store

      staticchildContextTypes={

      store:PropTypes.object.isRequired

      }

      //指定向子组件指定全局数据store

      getChildContext(){

      return{store:this.props.store};

      }

      render(){

      //返回所有子节点(如果没有子节点返回undefined,如果只有一个子节点它是对象,如果有多个它是数组)

      returnthis.props.children

      }

      }

      /*

      2.connect方法

      */

      exportfunctionconnect(mapStateToProps=()=>null,mapDispatchToProps={}){

      //返回函数(接收被包装组件类作为参数)

      return(WrapComponent)=>{

      //返回一个新的组件类

      returnclassConnectComponentextendsComponent{

      //声明接收全局store

      staticcontextTypes={

      store:PropTypes.object.isRequired

      }

      //构造函数的第2个参数为context对象

      constructor(props,context){

      super(props)

      console.log('constructor',this.context)//此时组件对象中还没有context

      //从context中取出store

      const{store}=context

      //一般属性:调用mapStateToProps函数得到包含所有需要传递一般属性的集合对象

      conststateProps=mapStateToProps(store.getState())

      //分发action的函数属性:调用自定义的整合函数生成包含多个分发action的函数的对象

      constdispatchProps=this.bindActionCreators(mapDispatchToProps)

      //初始化状态,包含所有需要传递给WrapComponent组件的一般属性

      this.state={

      ...stateProps

      }

      //将包含dispatch函数的对象保存在组件对象上(不用放到state中)

      this.dispatchProps=dispatchProps

      }

      /*

      根据包含多个actioncreator的对象,返回一个包含多个分发action的函数的对象

      */

      bindActionCreators=(mapDispatchToProps)=>{

      //准备一个保存分发action函数的对象容器

      constdispatchProps={}

      //遍历每个actioncreator

      Object.keys(mapDispatchToProps).forEach((key)=>{

      //得到某个actioncreator

      constactionCreator=mapDispatchToProps[key]

      //定义包含分发action代码的函数,并只在到准备好的容器中

      dispatchProps[key]=(...args)=>{

      this.context.store.dispatch(actionCreator(...args))

      }

      })

      //返回dispatch代码函数容器对象

      returndispatchProps

      }

      componentDidMount(){

      console.log('componentDidMount',this.constructor)

      //得到store

      const{store}=this.context

      //订阅监听

      store.subscribe(()=>{

      //一旦store中的state有变化,更新组件状态,从而导致被包装组件重新渲染

      this.setState(mapStateToProps(store.getState()))

      })

      }

      render(){

      return

      }

      }

      }

      }

      由于React的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来Web开发的主流工具。

    标签: 渲染UIReact

课课家教育

未登录