问题: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
constructor(props,context)
- componentWillReceiveProps(nextProps,nextContext)
- shouldComponentUpdate(nextProps,nextState,nextContext)
- componentWillUpdate(nextProps,nextContext)
- componentDidUpdate(prevProps,prevState,prevContext)
参考资料:
原文链接:https://www.f2er.com/react/305147.html