zoukankan      html  css  js  c++  java
  • ES6+ 开发 React 组件

    在这里简要的说一下这些语言新特性对 React 应用的开发有什么影响,这些 ES6+ 特性使得 React 开发更简单更有趣。

    迄今为止,最能体现我们使用 ES6+ 来编写 React 组件的就是我们选择使用类定义语法。替代了使用 React.createClass 方法来定义一个组件,我们可以定义一个 bonafide ES6 类来扩展 React.Component:

    1
    2
    3
    4
    5
    class Photo extends React.Component {
      render() {
        return <img alt={this.props.caption} src={this.props.src} />;
      }
    }

    现在,你就会发现一个微妙的差异 —— 当使用定义类的时候语法更简洁:

    1
    2
    3
    4
    5
    // The ES5 way
    var Photo = React.createClass({
      handleDoubleTap: function(e) { … },
      render: function() { … },
    });
    1
    2
    3
    4
    5
    // The ES6+ way
    class Photo extends React.Component {
      handleDoubleTap(e) { … }
      render() { … }
    }

    值得关注的是,我们去掉了两个括号和一个分号,每个方法声明我们省略了一个冒号,一个关键字和一个分号。

    当使用新的类定义时,所有的生命周期方法至少有一个是符合你期望的。类的 constructor 现在假设 role 之前是通过 componentWillMount 填充的:

    1
    2
    3
    4
    // The ES5 way
    var EmbedModal = React.createClass({
      componentWillMount: function() { … },
    });
    1
    2
    3
    4
    5
    6
    7
    // The ES6+ way
    class EmbedModal extends React.Component {
      constructor(props) {
        super(props);
        // Operations usually carried out in componentWillMount go here
      }
    }

    属性初始化程序

    在 ES6+ 类的世界里,prop types 和 defaults live 在类自身作为静态属性。这些,在组件的初始化状态也是一样的,可以使用 ES7 property initializers 定义:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // The ES5 way
    var Video = React.createClass({
      getDefaultProps: function() {
        return {
          autoPlay: false,
          maxLoops: 10,
        };
      },
      getInitialState: function() {
        return {
          loopsRemaining: this.props.maxLoops,
        };
      },
      propTypes: {
        autoPlay: React.PropTypes.bool.isRequired,
        maxLoops: React.PropTypes.number.isRequired,
        posterFrameSrc: React.PropTypes.string.isRequired,
        videoSrc: React.PropTypes.string.isRequired,
      },
    });
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // The ES6+ way
    class Video extends React.Component {
      static defaultProps = {
        autoPlay: false,
        maxLoops: 10,
      }
      static propTypes = {
        autoPlay: React.PropTypes.bool.isRequired,
        maxLoops: React.PropTypes.number.isRequired,
        posterFrameSrc: React.PropTypes.string.isRequired,
        videoSrc: React.PropTypes.string.isRequired,
      }
      state = {
        loopsRemaining: this.props.maxLoops,
      }
    }

    ES7 属性初始化程序操作内部类的 constructor,this 指向 construction 的类实例,所以初始化状态可以依赖于 this.props。值得关注的是,我们不再定义 prop 默认值和使用 getter 函数初始化状态对象。

    Arrow 函数

    React.createClass 方法用来在你的组件实例方法中执行一些额外的绑定工作,为了确保 this 关键字会指向组件实例: 

    1
    2
    3
    4
    5
    6
    7
    // Autobinding, brought to you by React.createClass
    var PostInfo = React.createClass({
      handleOptionsButtonClick: function(e) {
        // Here, 'this' refers to the component instance.
        this.setState({showOptionsModal: true});
      },
    });

    自从我们不参与 React.createClass 方法,而是使用 ES6+ 类语法定义组件,看似需要手动绑定实例方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Manually bind, wherever you need to
    class PostInfo extends React.Component {
      constructor(props) {
        super(props);
        // Manually bind this method to the component instance...
        this.handleOptionsButtonClick = this.handleOptionsButtonClick.bind(this);
      }
      handleOptionsButtonClick(e) {
        // ...to ensure that 'this' refers to the component instance here.
        this.setState({showOptionsModal: true});
      }
    }

    幸运的是,通过绑定两个 ES6+ 特性 – arrow functions 和属性初始化程序  – 可以选择绑定组件实例:

    1
    2
    3
    4
    5
    class PostInfo extends React.Component {
      handleOptionsButtonClick = (e) => {
        this.setState({showOptionsModal: true});
      }
    }

    ES6 的 arrow 函数体分享相同的词  this,用这来围绕他们的代码,这些可以达到我们预期的结果,也是 ES7 属性初始化程序在域内的方式。 Peek under the hood 来看看为什么能实现。

    动态属性名称 & 模板字符串

    其中一个对象常量增强是可以分配到一个派生属性名称。我们最初可能会像下面这样设置一些状态:

    1
    2
    3
    4
    5
    6
    7
    var Form = React.createClass({
      onChange: function(inputName, e) {
        var stateToSet = {};
        stateToSet[inputName + 'Value'] = e.target.value;
        this.setState(stateToSet);
      },
    });

    现在,我们有能力构造通过一个运行时 JavaScript 表达式确定属性名称的对象。这里,我们使用了一个模板字符串来确定哪个属性设置状态:

    1
    2
    3
    4
    5
    6
    7
    class Form extends React.Component {
      onChange(inputName, e) {
        this.setState({
          [`${inputName}Value`]: e.target.value,
        });
      }
    }

    解构 & 传播属性

    通常在编写组件的时候,我们可能想把大部分父组件的 props 传递给子组件,但不是所有。结合 ES6+ 解构和 JSX 传播属性,这个不需要多余的部分就能实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class AutoloadingPostsGrid extends React.Component {
      render() {
        var {
          className,
          ...others,  // contains all properties of this.props except for className
        } = this.props;
        return (
          <div className={className}>
            <PostsGrid {...others} />
            <button onClick={this.handleLoadMoreClick}>Load more</button>
          </div>
        );
      }
    }

    我们可以结合 JSX 传播属性和常规属性,利用一个简单的优先原则实现 overrides 和 defaults。这个元素会要求 className “override” 甚至是在 this.props 存在 className 属性: 

    1
    2
    3
    <div {...this.props} className="override">
       … 
    </div>

    这个元素常规来说需要 className “base” ,除非 this.props 有 className 属性覆盖: 

    1
    2
    3
    <div className="base" {...this.props}>
       … 
    </div>

    希望大家能享受 ES6+ 语言特性给 React 开发带来的一些便利。

  • 相关阅读:
    用JS + WCF打造轻量级WebPart
    提高WCF服务并发能力的简单处理办法
    利用JQuery实现更简单的Ajax跨域请求
    WCF Testing Tool(转)
    [转贴]一个有趣的布局
    [转贴].net中上传视频并将各种视频文件转换成.flv格式
    IE5,IE6,IE7,IE8的css兼容性列表[转自MSDN]
    [转贴]Castle 开发系列文章
    ie6,ie7,ff 的css兼容hack写法
    ExtJs学习笔记(23)ScriptTagProxy+XTemplate+WCF跨域取数据
  • 原文地址:https://www.cnblogs.com/smiler/p/5473314.html
Copyright © 2011-2022 走看看