美文网首页程序员半栈工程师
react-native组件方法扩展

react-native组件方法扩展

作者: 请叫我啊亮 | 来源:发表于2017-09-12 11:42 被阅读136次

需求:想让组件在挂载完成后打印输出当前组件名字。

作为一名ios开发者,依托oc强大的运行时,这个问题再简单不过了,但是js嘞?
最先想到的是替换组件Component.prototype原型链上的相关方法,但源码一看,发现componentDidMount不在组件的原型链方法之上,没法。

想起了es5中的mixins,大体实现如下:

const LogMixin = {
    componentDidMount: function () {
        console.log(this.componentName);
    }
};

export const ComponentA = React.createClass({
    mixins: [LogMixin],
    componentName : 'ComponentA',
    render: function () {
        return <View/>
    }
});

export const ComponentB = React.createClass({
    mixins: [LogMixin],
    componentName: 'ComponentB',
    render: function () {
        return  <View/>
    }
});

在组件ComponentA和ComponentB中添加上mixins属性,可以为当前组件扩展方法,且对生命周期方法并不会出现覆盖现象,扩展方法会先执行。系统的Touchable系列组件,如TouchableOpacity等使用了mixins作为组件方法扩展方式,值得学习。

mixins在es6中已经过期,官方提出的替代方案是高阶函数,实现如下

const Package = InnerComponent => class extends Component {
    static propTypes = {
        componentName: PropTypes.string.isRequired
    };

    componentDidMount() {
        console.log(this.props.componentName);
    }

    render() {
        return <InnerComponent {...this.props}/>;
    }
};

class ComponentC extends Component {
    render() {
        return <View><Text>我是内容组件</Text></View>
    }
}

export default Package(ComponentC)

Package是一个函数,参数InnerComponent是一个组件,返回值也是个继承自Component的组件,后面就是返回组件的实现方式。这个函数的作用就是对参数组件InnerComponent进行包装,扩充功能等。在这里,每次挂载目标组件ComponentC时,包装组件会先一步加载并调用componentDidMount方法打印出组件名字。

为了简化高阶函数的导出方式,增加代码可读性,可以采用es7提出的装饰器。非官方正式,而是babel提名,属于第三方。
首先安装:

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

再配置.babelrc文件

{
  "presets": ["react-native"],
  "plugins": [
    "transform-decorators-legacy"
  ]
}

使用

@Package
export default class ComponentC extends Component {
    render() {
        return <View><Text>我是内容组件</Text></View>
    }
}

@就是装饰器标识符,可以为组件、属性、方法等装饰另外的方法,这里Package作为一个方法装饰在组件ComponentC上面,效果跟上面完全一样。

相关文章