最近开始搞搞Taro,发现Taro当中好像没有mixin耶o(╥﹏╥)o,于是我开始去查阅文档,发现react在疯狂地diss mixin,原谅我才疏学浅,mixin在我看来只是命名冲突会有点烦,但尽量避免的话用起来还是很爽的。(可能没有经历过大项目吧)
那么,对于我们小项目就是想用mixin咋办?react就疯狂地给我们安利高阶组件(hoc)了。我们照着官网写个示例:
// withTest.js
import { Component } from '@tarojs/taro'
function withTest(Comp) {
return class extends Component {
render() {
return <Comp />
}
}
}
// A.js
import withTest from '../withTest'
@withTest
class A extends Component {}
export default A
在react环境里用hoc完全没问题,但是Taro环境就不一样了,它直接不调用hoc里返回class的render方法了,甚至还给你报了个错!
报错1.png
15764c13f5e2e4125dd583eab0b35360.jpg
解决这个报错呢,可以这样:
function withTest(Comp) {
return class extends Comp {
render() {
return <Comp />
}
}
}
虽说这样解决了报错,但render方法它始终不肯执行,其他的生命周期诸如componentWillMount等会执行。于是我去看了隔壁redux的connect源码,毕竟人家可以注入props到组件,人家也是高阶组件,要向它学习:
// 摘要代码
return class Connect extends Component {
constructor (props, isPage) {
super(Object.assign(...arguments, mergeObjects(mapStateToProps(store.getState(), props), initMapDispatch)), isPage)
Object.keys(initMapDispatch).forEach(key => {
this[`__event_${key}`] = initMapDispatch[key]
})
}
_constructor () {
if (!this.$scope) {
if (super._constructor) {
super._constructor(this.props)
}
return
}
const store = getStore()
Object.assign(this.props, mergeObjects(mapStateToProps(store.getState(), this.props), initMapDispatch))
unSubscribe = store.subscribe(stateListener.bind(this))
if (super._constructor) {
super._constructor(this.props)
}
}
componentWillUnmount () {
if (super.componentWillUnmount) {
super.componentWillUnmount()
}
if (unSubscribe) {
unSubscribe()
}
unSubscribe = null
}
}
什么嘛,原来connect根本就没有调render嘛,那么我们也不要去纠结于render方法了,干就完了。
披着高阶组件的外衣,mixin来了!
用法一(直接在类里写方法)
// withTest.js
function withTest(Comp) {
return class extends Comp {
a() { console.log('a'); }
b() {
this.a();
console.log('b');
}
}
}
// A.js
@withTest
class A extends Component {
componentWillMount() {
this.b();
// a
// b
}
}
用法二(state)
// 借助一个深拷贝对象的方法
const mergeObjects = function(obj1, obj2) {
const result = Object.assign({}, obj1);
if (isObject(obj1) && isObject(obj2)) {
for (const p in obj2) {
if (isObject(obj1[p]) && isObject(obj2[p])) {
result[p] = mergeObjects(obj1[p], obj2[p]);
} else {
result[p] = obj2[p];
}
}
}
return result;
};
// withTest.js
function withTest(Comp) {
return class extends Comp {
constructor(props) {
super(props);
this.state = mergeObjects(this.state, { a: 1 });
}
changeA(fn) {
this.setState({ a: 2 }, () => fn && fn());
}
}
}
// A.js
@withTest
class A extends Component {
constructor(props) {
super(props);
this.state = { a: 10, b: 2 };
}
componentWillMount() {
this.changeA(() => console.log(this.state));
// a: 2
// b: 2
}
}
网友评论