Taro中使用mixin

2020-01-03  本文已影响0人  kofzx

最近开始搞搞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
     }
}
上一篇 下一篇

猜你喜欢

热点阅读