模块开发之react-redux使用装饰器函数Decorator(九)
前言
这段时间一直搞前端模块开发,使用React
框架,配置redux
,中间使用react-redux
框架连接。注意到在类上添加@
符号,甚是不解,后来问其它人,才知道这是ES6新增装饰器函数。
它是一种特殊类型的声明,它可以附加到类声明、方法、参数或者属性上。装饰器由@
符号紧接一个函数名称。
但是目前大多数浏览器中以及node环境中都不支持装饰器修饰,故需要babel
转成低级别的JS代码。
装饰器函数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
对象中维护多个key
和value
,类似下面的
{
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装饰器使用方法基本上都是以上的情况。掌握上面的例子,在看别人写的代码或自己写装饰器都随心所意。