首页 > 其他分享 >2018_11_02_01

2018_11_02_01

时间:2024-10-08 22:33:49浏览次数:8  
标签:11 02 01 return Component React extends class PropsTypes

ES5&ES6 写法对照表(react)

来源:

React on ES6+
React/React Native 的 ES5 ES6 写法对照表

class 定义语法

值得注意的是,我们已经删除了两个括号和一个后缀分号,而对于每个声明的方法,我们都省略了一个冒号,一个 function 关键字和一个逗号。

class Photo extends React.Component {
    render() {
        return <img alt={this.props.caption} src={this.props.src} />
    }
}
// The ES5 way
var Photo = React.createClass({
    handleDoubleTap: function(e) { ... }
    render: function() { ... }
})
//ThE ES6 way
class Photo extends React.Component {
    handleDoubleTap(e) { ... }
    render() { ... }
}

生命周期方法

所有的生命周期方法,但可以定义为使用新的类语法期望的。该课程 constructor 现在承担以前填写的角色 componentWillMount:

// es5
var EmbedModal = React.createClass({
    componentWillMount: function() { ... }
})
// es6
class EmbedModal extends React.createClass (
    construtor(props) {
        super(props);
        // Operations usually carried out in componentWillMount go here
    }
)

属性初始化

ES7 属性初始化器在类的构造函数中运行,其中 this 指的是正在构建的类的实例,所以初始状态仍然可以依赖于 this.props。值得注意的是,我们不再需要根据吸气功能定义道具默认值和初始状态对象。

// es5
var Video = React.createClass({
  getDefaultProps: function() {
    return {
      autoPlay: flase,
      maxLoops: 10,
    };
  },
  getInitalState: function() {
    return {
      loopsRemaining: this.props.maxloops,
    };
  },
  propsTypes: {
    autoPlay: React.PropsTypes.bool.isRequired,
    maxloops: React.PropsTypes.number.isRequired,
    posterFrameSrc: React.PropsTypes.string.isRequired,
    videoSrc: React.PropsTypes.string.isRequired,
  },
});
// es6
class Video extends React.Component {
  static defaultProps = {
    autoPlay: false,
    maxloops: 10,
  };
  static propsTypes = {
    autoPlay: React.PropsTypes.bool.isRequired,
    maxloops: React.propsTypes.number.isRequired,
    posterFrameSrc: React.PropsTypes.string.isRequired,
    videoSrc: React.PropsTypes.string.isRequired,
  };
  state = {
    loopsRemaining: this.props.maxloops,
  };
}

箭头函数说明

该 React.createClass 方法用于对组件的实例方法执行一些额外的绑定工作,以确保其中的 this 关键字将引用该组件的实例。

// 自动绑定React.createClass
var PostInfo = React.createClass({
  handleOptionsButtonClick: function(e) {
    // 这里,'this' 是指组件实例。
    this.setState({ showOptionModal: true });
  },
});

由于我们 React.createClass 在使用 ES6 +类语法定义组件时不涉及该方法,所以我们需要手动绑定实例方法,无论我们想要这种行为:

// 手动绑定,无论你是否需要
class PostInfo extends React.Component {
  construtor(props) {
    super(props);
    // 手动将此方法绑定到组件实例中…
    this.handleOptionsButtonClick = this.handleOptionsButtonClick.bind(this);
  }
  handleOptionsButtonClick(e) {
    // …为了确保'this'指的是组件实例。
    this.setState({ showOptionsModal: true });
  }
}

幸运的是,通过组合两个 ES6 +功能 - 箭头函数和属性初始值设置 - 选择加入到组件实例的绑定变得轻而易举:

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

ES6 箭头函数的主体具有与它们周围 this 的代码相同的词汇,这使得我们获得了期望的结果,因为 ES7 属性初始化器的作用域的方式。在罩下看,看看为什么这个工作。

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

其中的增强对象文本包括分配给派生属性名称的能力。我们原本可以做这样的事情来设定一个状态:

var From = React.createClass({
  onChange: function(inputName, e) {
    var stateToSet = {};
    stateToSet[inputName + 'Value'] = e.targe.value;
    this.setState(stateToset);
  },
});
// 现在,我们有能力构建在运行时由JavaScript表达式决定其属性名称的对象。在这里,我们使用模板字符串来确定要设置的属性:
class From extends React.Component {
  onChange(inpuntName, e) {
    this.setState({
      [`$(inputName)value`]: e.targe.value,
    });
  }
}

解构和传播属性

通常在组成组件时,我们可能希望将大部分父组件的道具传递给子组件,但并不是全部。将 ES6 + 解构与 JSX 传播属性相结合,无需仪式即可实现:

class AutoloadingPostsGrid extends React.Component {
    render() {
        const {
            className,
            ...others // 包含所有特性this.props除了类名
        } = this.props;
        return (
            <div className={className}>
                <PostsGrid {...others} />
                <button onClick={this.handleLoadMoreClick}>Load more</button>
            </div>
        );
    }
}
// 我们可以将JSX传播属性与常规属性结合起来,利用简单的优先级规则来实现覆盖和默认值。该元素将获得className“覆盖”,即使存在一个className财产this.props:
<div {...this.props} className="override">
    ...
</div>
// This element will regularly have the “base” unless there exists a property in to override it:
<div className="base" {...this.props}>
  ...
</div>

模块

// 引用
// es5
var React = require("react");
var {
    Component,
    PropsTypes
} = React; //引用react抽象组件

var ReactNative = require("react-native");
var {
    Image,
    Text,
} = ReactNative; // 引用具体的React Native组件

// es6 import写法更为标准
import React, {
    Component,
    PropsTypes,
} from 'react';
import {
    imange,
    Text,
} from 'react-native'

导出单个类

在 ES5 里,要导出一个类给别的模块用,一般通过 module.exports 来导出

// es5
var MyComponent = React.createClass({
  // 函数
});
// es6
export default class MyComponent extends Component {
  // 函数
}
// 引用 class
// es5
var MyComponent = require('./MyComponent');
// es6
import MyComponent from './MyComponent';

定义组件

es5 在 ES5 里,通常通过 React.createClass 来定义一个组件类,像这样:

var Photo = React.createClass({
  render: function() {
    return <Image source={this.props.source} />;
  },
});

在 ES6 里,我们通过定义一个继承自 React.Component 的 class 来定义一个组件类,像这样:

class Photo extends React.Component {
  render() {
    return <Image source={this.props.source} />;
  }
}

给组件定义方法

给组件定义方法不再用 名字: function()的写法,而是直接用名字(),在方法的最后也不能有逗号了。

// es5
var Photo = React.createClass({
    componentWillMount: function() {
        // 函数
    },
    render: function() {
        return (
            <Image source={this.props.source} />
        );
    },
});

// es6
class Photo extends React.Component {
    componentWillMount() {
        // 函数
    },
    render() {
        return (
            <Image source={this.props.source} />
        );
    }
}

定义组件的属性类型和默认属性

在 ES5 里,属性类型和默认属性分别通过 propTypes 成员和 getDefaultProps 方法来实现

// es5
var video = React.createClass({
    getDefaultProps: function() {
        return {
            autoPlay: false,
            maxloops: 10,
        };
    },
    PropsTypes: {
        autoPlay: React.PropsTypes.bool.isRequired,
        maxloops: React.PropsTypes.number.isRequired,
        posterFrameSrc: React.PropsTypes.string.isRequired,
        videoSrc: React.PropsTypes.string.isRequired,
    },
    render: function() {
        return: function() {
            <View />
        };
    }
})

在 ES6 里,可以统一使用 static 成员来实现

//es6
class Video extends React.Component {
  static defaultProps = {
    autoPlay: flase,
    maxloops: 10,
  }; // 注意这里有分号
  static propsTypes = {
    autoPlay: React.PropsTypes.bool.isRequired,
    maxloops: React.PropsTypes.number.isRequired,
    posterFrameSrc: React.PropsTypes.string.isRequired,
    videoSrc: React.PropsTypes.string.isRequired,
  }; // 注意这里有分号
  render() {
    return <view />;
  }
}

也有人这么写,虽然不推荐,但读到代码的时候你应当能明白它的意思:

//es6
class Videlo extends React.Component {
  render() {
    return <Video />;
  }
}
Video.defauleftProps = {
  autoPlay: false,
  maxloops: 10,
};
Video.propsTypes = {
  autoPlay: React.PropsTypes.bool.isRequired,
  maxloops: React.PropsTypes.number.isRequired,
  posterFrameSrc: React.PropsTypes.string.isRequired,
  videoSrc: React.PropsTypes.string.isRequired,
};
// 注意: 对React开发者而言,static成员在IE10及之前版本不能被继承,而在IE11和其它浏览器上可以,这有时候会带来一些问题。React Native开发者可以不用担心这个问题。

初始化 STATE

// es5
var video = React.createClass({
  getInitalState: function() {
    return {
      loopsRemaining: this.props.maxloops,
    };
  },
});
// ES6下,有两种写法:
class Video extends React.Component {
  state = {
    loopsRemaining: this.props.maxloops,
  };
}
// 不过我们推荐更易理解的在构造函数中初始化(这样你还可以根据需要做一些计算):
// es6
class Video extends React.Component {
  construtor(props) {
    super(props);
    this.state = {
      loopsRemaining: this.props.maxloops,
    };
  }
}

把方法作为回调提供

很多习惯于 ES6 的用户反而不理解在 ES5 下可以这么做:

var PostInfo = React.createClass({
  handleOptionsButtonClick: function(e) {
    // Here,'this' refers to the component instance
    this.setState({ showOptionModel: true });
  },
  render: function() {
    return (
      <TouchableHighlight onPress={this.handleOptionsButtonClick}>
        <Text>{this.props.label}</Text>
      </TouchableHighlight>
    );
  },
});

在 ES5 下,React.createClass 会把所有的方法都 bind 一遍,这样可以提交到任意的地方作为回调函数,而 this 不会变化。但官方现在逐步认为这反而是不标准、不易理解的。

在 ES6 下,你需要通过 bind 来绑定 this 引用,或者使用箭头函数(它会绑定当前 scope 的 this 引用)来调用

// es6
class PostInfo extends React.Component
{
    handleOptionsButtonClick(e){
        this.setState({showOptionsModal: true});
    }
    render() {
        return (
            <TouchableHighlight
                onpress={this.handleOptionsButtonClick.bind(this)}
                onpress={e=>this.handleOptionsButtonClick(e)}
                >
                <Text>{this.props.label}</Text>
            </TouchableHighlight>
        )
    },
}

箭头函数

箭头函数实际上是在这里定义了一个临时的函数,箭头函数的箭头=>之前是一个空括号、单个的参数名、或用括号括起的多个参数名,而箭头之后可以是一个表达式(作为函数的返回值),或者是用花括号括起的函数体(需要自行通过 return 来返回值,否则返回的是 undefined)。

// 箭头函数实例
()=>1
v=>v+1
(a,b)=>a+b
()=>{
    alert('foo');
}
e=>{
    if (e == 0){
        return 0;
    }
    return 1000/e;
}

需要注意的是,不论是 bind 还是箭头函数,每次被执行都返回的是一个新的函数引用,因此如果你还需要函数的引用去做一些别的事情(譬如卸载监听器),那么你必须自己保存这个引用

// 错误的做法
class PaussMenu extends React.Component {
  componentWillMount() {
    AppStateIOS.addEventListener('change', this.onAppPaused.bind(this));
  }
  componentDidUnmount() {
    AppStateIOS.removeEventListener('change', this.onAppPaused.buid(this));
  }
  onAppPaused(event) {}
}

// 正确的做法
class PaussMenu extends React.Component {
  construtor(props) {
    super(props);
    this._OnAppPaused = this.onAppPaused.bind(this);
  }
  componentWillMount() {
    AppStateIOS.addEventListener('change', this._OnAppPaused);
  }
  componentDidUnmount() {
    AppStateIOS.removeEventListener('change', this_onAppPaused);
  }
  onAppPaused(event) {}
}
// 从这个帖子[这个帖子](http://www.tuicool.com/articles/Rj6RFnm)中我们还学习到一种新的做法:
// 正确的做法
class PaussMenu extends React.createClass {
  componentWillMount() {
    AppStateIOS.addEventListener('change', this.onAppPaused);
  }
  componentDidUnmount() {
    AppStateIOS.removeEventListener('change', this.onAppPaused);
  }
  onAppPaused = (event) => {
    // 把方法直接作为一个arrow function的属性来定义,初始化的时候就绑定好了this的指针
  };
}

Mixins

在 ES5 下,我们经常使用 minxin 来为我们的类添加一些新的方法,譬如 PureRenderMinxin

var PurRenderMixin = require('react-addins-pure-render-minxin');
React.createClass({
  mixin: [PurRenderMixin],

  render: function() {
    return <div className={this.props.className}>foo</div>;
  },
});

然而现在官方已经不再打算在 ES6 里继续推行 Mixin,他们说:Mixins Are Dead. Long Live Composition。

尽管如果要继续使用 mixin,还是有一些第三方的方案可以用,譬如这个方案

不过官方推荐,对于库编写者而言,应当尽快放弃 Mixin 的编写方式,文中提到 Sebastian Markbåge 的一段代码推荐了一种新的编码方式:

//Enhance.js
import { Component } from 'React'

extends var Enhance = ComposedComponent => class extends Component {
    construtor() {
        this.state = {dtaa:null}
    }
    componentDidUnmount() {
        this.setState({ data: 'Hello' });
    }
    render() {
        renturn <ComposedComponent {...this.props} data={this.state.data} />
    }
}

// HigherOrderComponent.js
import { Enhance } from "./Enhance";

class MyComponent {
    render() {
        if (!this.data) return <div>Waiting...</div>;
        return <div>{this.data}</div>;
    }
}

export defaule Enhance(MyComponent); // Enhance component
//用一个“增强函数”,来某个类增加一些方法,并且返回一个新类,这无疑能实现mixin所实现的大部分需求。

ES6+带来的其它好处

解构&属性延展

结合使用 ES6+的解构和属性延展,我们给孩子传递一批属性更为方便了。这个例子把 className 以外的所有属性传递给 div 标签:

class AutoloadingPostsGrid extends React.Component {
    render() {
        var {
            className,
            ...others,
        } = this.props;
        return (
            <div className={className}>
                <PostsGrid {...others} />
                <button onClick={this.handleOptionsButtonClick}>Load more</button>
            </div>
        );
    }
}

下面这种写法,则是传递所有属性的同时,用覆盖新的 className 值:

<div {...this.props} className="override">
  ...
</div>

这个例子则相反,如果属性中没有包含 className,则提供默认的值,而如果属性中已经包含了,则使用属性中的值

<div className="base" {...this.props}>
  ...
</div>

标签:11,02,01,return,Component,React,extends,class,PropsTypes
From: https://www.cnblogs.com/honghaitao/p/18453195

相关文章

  • 2018_10_28_01
    动态替换图片最简单的示例<divclass="img-wrapper"><divonclick='replacement'><imgsrc='[图片1]'></div><!-----------------><!--忽略同类型代码.--><!----------------->......
  • NewStar2024-week1
    前言:刚开始比赛,时间比较多尝试了一下所有题目,难度也很友好,之后就写密码了,写全部太累了Week1CryptoBase4C4A575851324332474E324547554B494A5A4446513653434E564D444154545A4B354D45454D434E4959345536544B474D5134513D3D3D3D秒了一眼秒了p,q相近或者factordb查"""fro......
  • NOIP2024集训 Day47 总结
    前言人有两次生命,当他意识到只有一次的时候,第二次生命就开始最小生成树和二分图匹配专题,感觉总体都比较套路。但是这些套路为啥感觉见都没见过啊,怪不得做这么慢。色观察到对于最终答案显然都是最小生成树上一条两个端点颜色不同的边。而这个题并不会改变图的形态,仅仅是改......
  • Cornell cs3110 - Chapter9 Lessons
    使用Menhir构建SimPL的编译器LexerandParser语法分析模块Lexer,Parser,AST是三个依次耦合的模块,可以这么描述三者的关系:Lexer---tokens-->Parser---nodes-->AST相对于上面的图像化描述,cs3110反过来构建整个Lexer和Parser的结构在ast.ml中,定义了AST上......
  • CSP2024-33
    2A题意:给定一个01串,每次可以循环移动一个子串,求多少次操作使整串有序(升序)。每次操作至多使极大全1段个数减一:111100001111\(\to\)000011111111。数一下一开始有多少全1段,判断一下最后一个元素是否是1即可。submissionA题意:给定\(n,m,a,b,k\),求满足\(ax+by=k,\x,......
  • YOLO11改进 | 注意力机制 | 反向残差注意力机制
     秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转......
  • YOLO11改进 | 注意力机制 | 十字交叉注意力机制CrissCrossAttention【含目标检测,语义
    秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转......
  • NOIP2024集训Day47 生成树+二分图
    NOIP2024集训Day47生成树+二分图B.[THUPC2022初赛]最小公倍树直接建边显然不行,考虑优化建边。对于两个点\(u,v\),\((u,v)\)的边权为\(\displaystyle\operatorname{lcm}(u,v)=\frac{u\timesv}{\gcd(u,v)}\),显然应该选择\(\gcd(u,v)\)尽可能大的点对连边,也就是......
  • CSP2024 前集训:csp-s模拟10
    前言T2赛时不会,T3没有想到移项遂打了个背包得\(50pts\),T4又放回滚莫队板子,结过开太晚了没打完,以后板子麻烦放靠前点谢谢。T1需要线性基思想,听5k讲完貌似懂了,但是学了再回来补吧。T2首先选择一个度数不是\(1\)的点当根。对于一个非叶子节点\(p\)被扫到有两种情况......
  • 学年(2024-2025-3) 学号(20241424)《计算机基础与程序设计》第三周学习总结
    学期(2024-2025-3)学号(20241424)《计算机基础与程序设计》第三周学习总结作业信息|这个作业属于([2024-2025-3-计算机基础与程序设计](https://www.cnblogs.com/rocedu/p/9577842.html#WEEK03)||-- |-- ||这个作业要求在(2024-2025-3计算机基础与程序设计第三周作业)||这个作业......