react-intl中injectIntl方法的源码简析

前端之家收集整理的这篇文章主要介绍了react-intl中injectIntl方法的源码简析前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

问题:react-intl用法部分

function Home(props) {
  return (
    <DocumentTitle title={`Ant Design - ${props.intl.formatMessage({ id: 'app.home.slogan' })}`}>
      <div className="main-wrapper">
        <Link />
        <Banner {...props} />
        <Page1 {...props} />
        <Page2 {...props} />
        <Page3 {...props} />
        <Page4 {...props} />
        <style dangerouslySetInnerHTML={{ __html: getStyle() }} />
      </div>
    </DocumentTitle>
  );
}

export default injectIntl(Home);//传入一个包裹组件WrappedComponent,返回一个InjectIntl组件实例

问题:源码分析部分

/*
 * Copyright 2015,Yahoo Inc.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

// Inspired by react-redux's `connect()` HOC factory function implementation:
// https://github.com/rackt/react-redux

import React,{Component} from 'react';
import invariant from 'invariant';
import {intlShape} from './types';
import {invariantIntlContext} from './utils';

function getDisplayName(Component) {
    return Component.displayName || Component.name || 'Component';
}

export default function injectIntl(WrappedComponent,options = {}) {
    const {
        intlPropName = 'intl',withRef      = false,//为WrappedComponent添加一个ref属性
    } = options;

    class InjectIntl extends Component {
        static displayName = `InjectIntl(${getDisplayName(WrappedComponent)})`;

        static contextTypes = {//可以接受父组件存放在context中的intl属性
            intl: intlShape,};

        static WrappedComponent = WrappedComponent;

        constructor(props,context) {
            super(props,context);
            invariantIntlContext(context);
        }
         //getWrappedInstance调用时候欧返回我们的ref="wrappedInstance"
        getWrappedInstance() {
            invariant(withRef,'[React Intl] To access the wrapped instance,' +
                'the `{withRef: true}` option must be set when calling: ' +
                '`injectIntl()`'
            );

            return this.refs.wrappedInstance;
        }

        render() {
            return (
                <WrappedComponent //我们的WrappedComponent会被存放一个intl属性作为props,这是为什么上面的例子可以通过props直接获取到
                    {...this.props}
                    {...{[intlPropName]: this.context.intl}}//如果有ref属性,那么返回我们的WrappedComponent实例
                    ref={withRef ? 'wrappedInstance' : null}
                />
            );
        }
    }

    return InjectIntl;
}

问题:为什么要用这个InjectIntl而不是直接放在Context中,就像下面的例子就是直接放在context中的

import React,{PropTypes} from 'react';
import {intlShape,FormattedRelative} from 'react-intl';

const Component = ({date},context) => ( //如果有ContextTypes,那么第二个参数就是我们的context
    <span title={context.intl.formatDate(date)}> //change here,use context directly
        <FormattedRelative value={date}/>
    </span>
);

Component.propTypes = {
    date: PropTypes.any.isrequired,};

Component.contextTypes = {
    intl: intlShape.isrequired,}
export default Component;

而下面的例子就是通过injectIntl来完成的

import React,{PropTypes} from 'react';
import {injectIntl,intlShape,FormattedRelative} from 'react-intl';

const Component = ({date,intl}) => (
    <span title={intl.formatDate(date)}>
        <FormattedRelative value={date}/>
    </span>
);

Component.propTypes = {
    date: PropTypes.any.isrequired,intl: intlShape.isrequired,};
export default injectIntl(Component);

injectIntl提供了一个非直接层,他的作用是解耦,使用React的intl来替代我们的React的context。如果以后React的context的API发生变化,代码的改变只要在injectIntl中进行就可以了,而不是在整个应用中


问题:方才说了第二个参数是context,我们看看都有哪些方法会传入第二个参数context


参考资料:

react-intl

原文链接:https://www.f2er.com/react/305147.html

猜你在找的React相关文章