模块开发之react-redux使用装饰器函数Decorator(九)

模块开发之react-redux使用装饰器函数Decorator(九)

前言

这段时间一直搞前端模块开发,使用React框架,配置redux,中间使用react-redux框架连接。注意到在类上添加@符号,甚是不解,后来问其它人,才知道这是ES6新增装饰器函数。
它是一种特殊类型的声明,它可以附加到类声明、方法、参数或者属性上。装饰器由@符号紧接一个函数名称。
但是目前大多数浏览器中以及node环境中都不支持装饰器修饰,故需要babel转成低级别的JS代码。

阮一峰的Decorator


装饰器函数Decorator

例子

@testable
class MyTestableClass {
  // ...
}

function testable(target) {
  target.isTestable = true;
}

MyTestableClass.isTestable // true

testable是一个函数,接收一个类做为对象,同时在类上添加一个静态对象,@testable修饰在类上,类当作参数传入装饰器函数里。
装饰器函数不仅可以是一个无返回的函数,也可以是返回一个函数的函数。类似如下

function testable(isTestable) {
  return function(target) {
    target.isTestable = isTestable;
  }
}

@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true

使用@符号放在类上,装饰器函数接收类做为第一个参数,可以对类做一些操作。这就是装饰器函数用来给附着的主体进行装饰,添加额外行为的一种方式。

修饰器本质就是编译时执行的函数,不是运行时执行的函数。

这里只介绍装饰器修饰在类上,其它的类属性和类方法里跳转链接自己学习。
总结一句话就是,使用@符号后面紧跟一个函数,这个函数的第一个参数是类,在函数里可以做一些对类的相关操作,这就是装饰器函数。


react-redux里使用装饰器函数

安装依赖

使用label这个loader支持Decorator功能。

npm install babel-plugin-transform-decorators-legacy --save-dev

项目根目录的.babelrc文件里添加如下(若没有该文件则创建,注意使用dos命令)

{
    "plugins": [
        "transform-decorators-legacy"
    ]
}

这样我们就能在项目里使用装饰器函数了。
connect(mapStateToProps, mapDispatchToProps)方法,我们知道connect返回一个函数,这个函数接收一个组件当参数,这个可以当成装饰器函数。

源始的connect使用方式

import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import userAction from "../action/Action";//action creator路径,换成自己的。
class MyReactComponent extends React.Component {}

function mapStateToProps(state){
    return state;
}
function mapDispatchToProps(dispatch){
    return bindActionCreators(userAction,dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);

userAction是一个action creator。下面的例子中模块引入省略。

最简单的connect装饰器函数

@connect(mapStateToProps, mapDispatchToProps)
class MyReactComponent extends React.Component {}

function mapStateToProps(state){
    return state;
}
function mapDispatchToProps(dispatch){
    return bindActionCreators(userAction,dispatch)
}

或者更简洁的写法,使用Lambda表达式如下

@connect(state => state.user, dispatch => bindActionCreators(userAction, dispatch))
class MyReactComponent extends React.Component {}

稍微复杂的方式

单独将connect(mapStateToProps, mapDispatchToProps)抽出来,存放在一个文件connect.js(名字随便取)中做为模块使用,在组件上直接使用@connect()即可。

//connect.js
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import userAction from "../action/Action";

const mapStateToProps = state => state
const mapDispatchToProps = dispatch => bindActionCreators(userAction, dispatch)
export default connect(mapStateToProps, mapDispatchToProps)

//MyReactComponent.jsx
//组件上
import connect from './connect'
@connect
class MyReactComponent extends React.Component {}

再高一级使用方式

假设redux的实例store维护的state对象中维护多个keyvalue,类似下面的

{
main:{数据},
user:{数据},
role:{数据}
...
}

我们可以将创造connect装饰器函数再抽成一个模块函数,相当于装饰器函数的工厂。

//baseConnectFactory.j
//函数工厂模块,可以接收数组
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

//stateKey是state里的key,action是传入的action creator
export default (stateKey,action)=>connect (
    state=>{
        let s = {}
        if(stateKey instanceof Array){
            stateKey.forEach(k=>s[k]=state[k])
        }else{
            s=state[stateKey]
        }
        return s
    },
    dispatch=>{
        let a = {}
        if(action instanceof Array){
            action.forEach(act=>a[act.name]=bindActionCreators(act,dispatch))
        }else{
            a = bindActionCreators(action,dispatch)
        }
        return a
    }
)

//MyReactComponentConnect.js
//在需要使用装饰器的地方传入真实数据,构造装饰器函数
import connect from './baseConnectFactory'//引入aseConnectFactory.js模块
import userAction from '../user/action/Action'//引入action creator模块
//导出装饰器函数
export default connect (['main','user'],userAction)

//MyReactComponent.jsx
//组件上
import connect from './MyReactComponentConnect'
//直接使用装饰器
@connect
class MyReactComponent extends React.Component {}

总结

react-redux的connect装饰器使用方法基本上都是以上的情况。掌握上面的例子,在看别人写的代码或自己写装饰器都随心所意。

猜你喜欢

转载自blog.csdn.net/achenyuan/article/details/80862567