由于本期采用的小程序框架是taro 偶然看到以下写法
@connect(({ counter }) => ({
counter
}), (dispatch) => ({
add() {
dispatch(add())
}
}))
class Index extends Component {}
看了typescript才发现是装饰器 官方文档如下
https://www.tslang.cn/docs/handbook/decorators.html#class-decorators
装饰器在js中还在建议搜集阶段,所以很少人使用,bable 安装插件也是可以支持的,目前babel编译器已经支持装饰器了,装饰器分为5种:类装饰器 方法装饰器 访问器装饰器 属性装饰器 参数装饰器
装饰器,顾名思义就是在装饰类,看前面的代码,这个connect的作用就是为了后面的 class index 这个类添加一些内部属性和方法,方便组件内部引用 添加的这些属性和方法都是通过传参过去的 所以组件的压力没那么大 都是一些必须要的属性和方法
这里我们只解析类装饰器,在taro当中tarojs > redux > src里面可以找到connect的源码大概就是下面这些:为了学习, 逐行理解
import { getStore } from '../utils/store' // 从store引入了一个taro获得store的方法
import { mergeObjects, isObject } from '../utils' // 引入两个方法 深拷贝 和 判断是否为对象
export default function connect (mapStateToProps, mapDispatchToProps) { // 参数为两个方法
const store = getStore() // 获取当前的store
const dispatch = store.dispatch // 变量dispatch
const initMapDispatch = typeof mapDispatchToProps === 'function' ? mapDispatchToProps(dispatch) : {} // 判断传入的mapDispatchToProps是否为方法来初始化组件的内部方法对象
initMapDispatch.dispatch = dispatch
const stateListener = function () {
let isChanged = false
const newMapState = mapStateToProps(store.getState())
Object.keys(newMapState).forEach(key => {
let val = newMapState[key]
if (isObject(val) && isObject(initMapDispatch[key])) {
val = mergeObjects(val, initMapDispatch[key])
}
this.prevProps = Object.assign({}, this.props)
if (this.props[key] !== val) {
this.props[key] = val
isChanged = true
}
})// 这一整个方法是根据传入的参数初始化state对象, 并且判断initMapDispatch是否有同名属性 ,如果有, 进行mergeObjects合并
const isPageHide = this.$root ? this.$root.$isPageHide : this.$isPageHide
if (isChanged && !isPageHide) {
this._unsafeCallUpdate = true
this.setState({}, () => {
delete this._unsafeCallUpdate
})
}
} // 这个略过
// 从这里开始才是在编译时执行的方法
return function connectComponent (Component) { // 这里的Component参数 就是后面的类
let unSubscribe = null
return class Connect extends Component { // 返回一个派生类
constructor () { // 重写index类的constructor 并为它写入传入的state和方法
super(Object.assign(...arguments, mergeObjects(mapStateToProps(store.getState()), initMapDispatch)))
Object.keys(initMapDispatch).forEach(key => {
this[`__event_${key}`] = initMapDispatch[key]
})
}
componentWillMount () { // 重写componentWillMount
const store = getStore()
Object.assign(this.props, mergeObjects(mapStateToProps(store.getState()), initMapDispatch))
unSubscribe = store.subscribe(stateListener.bind(this))
if (super.componentWillMount) {
super.componentWillMount()
}
}
// ... 同理以下都是重写方法
componentDidShow () {}
componentDidHide () {}
componentWillUnmount () { }
}
}
}
网友评论