es6 native react 模块
2016-04-10 23:17:14 u010376098 阅读数 6882
  • 概述:
开发的过程中,有很多需要抽象出来可以拿来公用的模块,比如App的顶栏
本文就介绍一下ES6怎么写独立的模块的导出和导入。
  • 详细内容:
我们先创建一个独立的js文件
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */

import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  PixelRatio,
  View,
} from 'react-native';

class Header extends Component {
/*
  api自带渲染函数,重写该方法
*/
  render() {
    return (
      <View style={styles.flex}>
        <Text style= {styles.font}>
          <Text style = {styles.font_1}>
            网易
          </Text>

          <Text style = {styles.font_2}>
            新闻
          </Text>

          <Text>
            有态度°
          </Text>
        </Text>
      </View>
    );
  }
}

//定义样式
const styles = StyleSheet.create({
  flex:{
    marginTop: 25,
    height: 50,
    borderBottomWidth: 3/React.PixelRatio.get(),
    borderBottomColor: "#EF2D36",
    alignItems: "center",
  },
  font:{
    fontSize: 25,
    fontWeight: "bold",
    textAlign: "center",
  },
  font_1:{
    color: "#CD1D1C",
  },
  font_2:{
    color: "#FFF",
    backgroundColor: "#CD1D1C",
  },
});

  /**
   * 导出该类作为独立的模块
   */
    export default class MyHeader extends Header {
  }

此处最关键的就是
/**
   * 导出该类作为独立的模块
   */
    export default class MyHeader extends Header {
  }
MyHeader是自己创建的类名称,导入的时候用到,这里extends继承的就是Header类;
到这里自定义的类导出写法就完成了。

接下来是介绍怎么导入抽出来的类写法:
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */

import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View,
} from 'react-native';

// import MyComponent from './MyComponent.js';
/**
 *  导入自己写好的header类
 */
 import MyHeader from './Header.js';


class TestProject extends Component{
/*
  api自带渲染函数,重写该方法
*/
  render() {
    return (
      <View style = {styles.flex}>
        <MyHeader></MyHeader>
      </View>
    );
  }
}

//定义样式
const styles = StyleSheet.create({
  flex:{
    flex: 1,
  },
});
//注册项目
AppRegistry.registerComponent('TestProject', () => TestProject);

关键的就一句话:
 import MyHeader from './Header.js';

这里的MyHeader就是前面导出类写到的,在这里用到,from表示从哪里加载这个定义好的文件。
到这里,就全部完成了独立抽象模块的导出和导入ES6写法。


2018-07-31 15:17:22 u013245224 阅读数 75

1.变量的声明 : var 或者 let

 var 和 let 有如此......这般不同等等

虽然大部分现有的代码都是var 总之你始终使用let就好了

2.常量的声明:const

const one = 1 

3.没有声明或者声明没有值的都是undefine

4.箭头函数:

箭头函数类似于很多语言的中有的lambda表达式,更接近于函数的数学表达式

例如:f(x) = πx²  实际我们可以使用箭头函数   

(x) => 3.14 * x *x

输入 =>  输出

参数 => 返回值

我们只需要记住两种函数方法

class 外部:  

 let 函数名 = (参数) => {内部逻辑}

class  内部:

class SomeComponent extends Component {

       方法名 = (参数) => {

              内部逻辑             

              }

}

务必记住:如果箭头函数的代码块部分使用了大括号,则此时切莫忘了使用了return语句返回:

() => {return 1;}

 

5.扩展运算符

···扩展运算符好比是把一个压缩包解压到当前目录

//数组

let a = [1,2,3];

console .log(···a)   //1 2 3

//对象

let z = {a:3,b:4};

let n = (···z);

console.log(n);    //{a:3,b:4}

 

7.结构

let [a,b,c] = [1,2,3]

console.log(a,b,c)  //1 2 3

 

8.模块的导入和导包 

import ooxx from  '???'

'ooxx'  引用node_module/ooxx/index.js 或是node_modules/ooxx/package.js中main字段所指的js文件

'./a' 引用同目录下的a.js文件 注意 './'不能省略 js后缀可写可不写

'../a/b' 引用父目录中的a目录中的b.js文件,如果b也为目录 表示引用本目录下的index.js文件

 

9. 数组的新增方法(include,map)

//数组查找元素

[1,2,3].include(3)   //true

//字符串

'hello'.include('hell') ;  

//map返回等长的新数组

let odds = [1,2,3,4]

let events = odds.map(n => n+1) ;   //2 3 4 5

let names = ['zhangsan' ,'lisi']

let namesText = names.map(n => <Text>{n}</Text>)

另附  ES6模块的import和export用法总结

2017-09-01 18:32:00 weixin_34198453 阅读数 19

React Native 是基于 React 这个前端框架来构建native app的架构。React Native基于ES6(即ECMAScript2015)语言进行开发的。


ES6基础

我大概在13年的时候学过一阵子的JavaScript,ES5。
如果学JavaScript的话,还是推荐


《JavaScript高级程序设计》

这本书真的是太经典了,学完这个后再去看ECMAScript6,那时真的会发现,6真的是太人性化了,如果一开始就学6,可能不会很难体会到她的那种魅力吧。学习ES6,还是看看 阮一峰老师的 ECMAScript 6 入门

1833901-6f26fc39d64a1bde.jpg
《ECMAScript 6 入门》

不过这本书是基于ES5的。

JavaScript时间轴:

下面就是一个简单的JavaScript发展时间轴:

1、1995:JavaScript诞生,它的初始名叫LiveScript。

2、1997:ECMAScript标准确立。

3、1999:ES3出现,与此同时IE5风靡一时。

4、2000–2005: XMLHttpRequest又名AJAX, 在Outlook Web Access (2000)、Oddpost (2002),Gmail (2004)和Google Maps (2005)大受重用。

5、2009: ES5出现,(就是我们大多数人现在使用的)例如foreach,Object.keys,Object.create和JSON标准。

6、2015:ES6/ECMAScript2015出现。

JS的组成
1)  核心(ECMAScript):描述了该语言的语法和基本对象。担当的是一个翻译的角色;是一个解释器;帮助计算机来读懂我们写的程序;实现加减乘除, 定义变量;
2) 文档对象模型(DOM):描述了处理网页内容的方法和接口。文档指的就是网页;把网页变成一个JS可以操作的对象;给了JS可以操作页面元素的能力;
3) 浏览器对象模型(BOM):描述了与浏览器进行交互的方法和接口。给了JS操作浏览器的能力;

我这里从ES6的十大特性出发整理一下ES6,整理来自前端开发者不得不知的ES6十大特性ECMAScript 6 入门 , 这里在内容上做了丰富。

1) Block-Scoped Constructs Let and Const(块作用域构造Let and Const)

首先我们来看看这个例子:

var name = 'Emily'

while (true) {
    var name = 'Anthony'
    console.log(name)  //Anthony
    break
}

console.log(name)  //Anthony

let name = 'Emily'

while (true) {
    let name = 'Anthony'
    console.log(name)  //Anthony
    break
}

console.log(name)  //Emily

使用var两次输出都是"Anthony",这是因为ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。第一种场景就是你现在看到的内层变量覆盖外层变量。而let则实际上为JavaScript新增了块级作用域。用它所声明的变量,只在let命令所在的代码块内有效。

那么你可能就会理解下面的代码为什么用let取代var了。

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10
var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

const也用来声明变量,但是声明的是常量。一旦声明,常量的值就不能改变。

const PI = Math.PI

PI = 23 //Module build failed: SyntaxError: /es6/app.js: "PI" is read-only

const有一个很好的应用场景,就是当我们引用第三方库的时声明的变量,用const来声明可以避免未来不小心重命名而导致出现bug:

const monent = require('moment')
2) Default Parameters(默认参数) in ES6

同样是对比,ES5中我们这样指定默认值。

var link = function (height, color, url) {
    var height = height || 50;
    var color = color || 'red';
    var url = url || 'http://azat.co';
    ...
}

现在呢,ES6中,我们可以直接指定默认值:

var link = function(height = 50, color = 'red', url = 'http://azat.co') {
  ...
}

还可以这样:

function animals(...types){
    console.log(types)
}
animals('cat', 'dog', 'fish') //["cat", "dog", "fish"]
3) Template Literals (模板文本)in ES6

在ES5和Java语言中,我们可以这样组合一个字符串:

var name = 'Your name is ' + first + ' ' + last + '.';
var url = 'http://localhost:3000/api/messages/' + id;

在ES6中,我们可以使用新的语法$ {NAME},并把它放在反引号里:

var name = `Your name is ${first} ${last}. `;
var url = `http://localhost:3000/api/messages/${id}`;
4) Multi-line Strings (多行字符串)in ES6

ES6的多行字符串是一个非常实用的功能。在ES5和Java中,我们不得不使用以下方法来表示多行字符串:

var roadPoem = 'Then took the other, as just as fair,nt'
    + 'And having perhaps the better claimnt'
    + 'Because it was grassy and wanted wear,nt'
    + 'Though as for that the passing therent'
    + 'Had worn them really about the same,nt';
var fourAgreements = 'You have the right to be you.n
    You can only be you when you do your best.';

然而在ES6中,仅仅用反引号就可以解决了:

var roadPoem = `Then took the other, as just as fair,
    And having perhaps the better claim
    Because it was grassy and wanted wear,
    Though as for that the passing there
    Had worn them really about the same,`;
var fourAgreements = `You have the right to be you.
    You can only be you when you do your best.`;
5) Destructuring Assignment (解构赋值)in ES6

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

let cat = 'ken'
let dog = 'lili'
let zoo = {cat: cat, dog: dog}
console.log(zoo)  //Object {cat: "ken", dog: "lili"}

用ES6完全可以像下面这么写:

let cat = 'ken'
let dog = 'lili'
let zoo = {cat, dog}
console.log(zoo)  //Object {cat: "ken", dog: "lili"}

反过来可以这么写:

let dog = {type: 'animal', many: 2}
let { type, many} = dog
console.log(type, many)   //animal 2
6 ) Arrow Functions (箭头函数)in ES6

这个恐怕是ES6最最常用的一个新特性了,用它来写function比原来的写法要简洁清晰很多:

function(i){ return i + 1; } //ES5
(i) => i + 1 //ES6

简直是简单的不像话对吧...
如果方程比较复杂,则需要用{}把代码包起来:

function(x, y) { 
    x++;
    y--;
    return x + y;
}
(x, y) => {x++; y--; return x+y}

除了看上去更简洁以外,arrow function还有一项超级无敌的功能!
长期以来,JavaScript语言的this对象一直是一个令人头痛的问题,在对象方法中使用this,必须非常小心。例如:

class Animal {
    constructor(){
        this.type = 'animal'
    }
    says(say){
        setTimeout(function(){
            console.log(this.type + ' says ' + say)
        }, 1000)
    }
}

 var animal = new Animal()
 animal.says('hi')  //undefined says hi

运行上面的代码会报错,这是因为setTimeout中的this指向的是全局对象。所以为了让它能够正确的运行,传统的解决方法有两种:

第一种是将this传给self,再用self来指代this

 says(say){
     var self = this;
     setTimeout(function(){
         console.log(self.type + ' says ' + say)
     }, 1000)

2.第二种方法是用bind(this),即

 says(say){
     setTimeout(function(){
         console.log(self.type + ' says ' + say)
     }.bind(this), 1000)

但现在我们有了箭头函数,就不需要这么麻烦了:

class Animal {
    constructor(){
        this.type = 'animal'
    }
    says(say){
        setTimeout( () => {
            console.log(this.type + ' says ' + say)
        }, 1000)
    }
}
 var animal = new Animal()
 animal.says('hi')  //animal says hi

当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this。

7) Promises in ES6

JS本身是单线程的语言,它要实现异步都是通过回调函数来实现的。
Promises象征着一个异步操作的最终结果。Promises交互主要通过它的then方法,then方法接受一个回调函数,这个回调函数接受执行成功的返回值或执行失败的错误原因,错误原因一般是Error对象。需要注意的是,then方法执行的返回值是一个Promise对象,而then方法接受的回调函数的返回值则可以是任意的JavaScript对象,包括Promises。基于这种机制,Promise对象的链式调用就起作用了。

在ES6中有标准的Promise实现。
下面是一个简单的用setTimeout()实现的异步延迟加载函数:

setTimeout(function(){
  console.log('Yay!');
}, 1000);

在ES6中,我们可以用promise重写:

var wait1000 =  new Promise(function(resolve, reject) {
  setTimeout(resolve, 1000);
}).then(function() {
  console.log('Yay!');
});

或者用ES6的箭头函数:

var wait1000 =  new Promise((resolve, reject)=> {
  setTimeout(resolve, 1000);
}).then(()=> {
  console.log('Yay!');
});

到目前为止,代码的行数从三行增加到五行,并没有任何明显的好处。确实,如果我们有更多的嵌套逻辑在setTimeout()回调函数中,我们将发现更多好处:

setTimeout(function(){
  console.log('Yay!');
  setTimeout(function(){
    console.log('Wheeyee!');
  }, 1000)
}, 1000);

在ES6中我们可以用promises重写:

var wait1000 =  ()=> new Promise((resolve, reject)=> {setTimeout(resolve, 1000)});
wait1000()
    .then(function() {
        console.log('Yay!')
        return wait1000()
    })
    .then(function() {
        console.log('Wheeyee!')
    });

推荐文章:
ES6 JavaScript Promise的感性认知

初识JavaScript Promises

Introduction to ES6 Promises – The Four Functions You Need To Avoid Callback Hell

8) Classes(类) in ES6

class, extends, super这三个特性涉及了ES5中最令人头疼的的几个部分:原型、构造函数,继承...你还在为它们复杂难懂的语法而烦恼吗?你还在为指针到底指向哪里而纠结万分吗?

有了ES6我们不再烦恼!

ES6提供了更接近传统语言的写法,引入了Class(类)这个概念。新的class写法让对象原型的写法更加清晰、更像面向对象编程的语法,也更加通俗易懂。

class Animal {
    constructor(){
        this.type = 'animal'
    }
    says(say){
        console.log(this.type + ' says ' + say)
    }
}

let animal = new Animal()
animal.says('hello') //animal says hello

class Cat extends Animal {
    constructor(){
        super()
        this.type = 'cat'
    }
}

let cat = new Cat()
cat.says('hello') //cat says hello

上面代码首先用class定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。简单地说,constructor内定义的方法和属性是实例对象自己的,而constructor外定义的方法和属性则是所有实力对象可以共享的。

Class之间可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。上面定义了一个Cat类,该类通过extends关键字,继承了Animal类的所有属性和方法。

super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。

ES6的继承机制,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。
P.S 如果你写react的话,就会发现以上三个东西在最新版React中出现得很多。创建的每个component都是一个继承React.Component
的类。详见react文档

9) Modules(模块) in ES6

众所周知,在ES6以前JavaScript并不支持本地的模块。人们想出了AMD,RequireJS,CommonJS以及其它解决方法。现在ES6中可以用模块import 和export 操作了。
在ES5中,你可以在 <script>中直接写可以运行的代码(简称IIFE),或者一些库像AMD。然而在ES6中,你可以用export导入你的类。下面举个例子,在ES5中,module.js有port变量和getAccounts 方法:

module.exports = {
  port: 3000,
  getAccounts: function() {
    ...
  }
}

在ES5中,main.js需要依赖require('module') 导入module.js:

var service = require('module.js');
console.log(service.port); // 3000 

但在ES6中,我们将用export and import。例如,这是我们用ES6 写的module.js文件库:

export var port = 3000;
export function getAccounts(url) {
  ...
}

如果用ES6来导入到文件main.js中,我们需用import {name} from 'my-module'语法,例如:

import {port, getAccounts} from 'module';
console.log(port); // 3000

或者我们可以在main.js中把整个模块导入, 并命名为 service:

import * as service from 'module';
console.log(service.port); // 3000

从我个人角度来说,我觉得ES6模块是让人困惑的。但可以肯定的事,它们使语言更加灵活了。
更多的信息和例子关于ES6模块,请看 this text。不管怎样,请写模块化的JavaScript。

10) Enhanced Object Literals (增强的对象文本)in

ES6
具体可以看文章:前端开发者不得不知的ES6十大特性

JavaScript是基于原型的面对象语言
理解这一点,对使用JS开发还是比较重要的。
像Java,Objective C,C++都是基于类的面向对象语言。
面向对象语言有两个:
基于类的面向对象语言
主要有两个概念
类(class):定义了一组具有某一类特征的事务。类是抽象的,比如鸟类
实例(instance):实体是类的实体话提现,比如一只鸟
基于原型的面向对象
基于原型的面向对象语言并不存在这种区别,基于原型的面向对象语言所有的都是对象。基于原型的面向对象语言有一个概念叫做原型对象,古代有一种东西叫做活字印刷术,那一个个字的模版就是这里的原型对象。

下一篇文章是React Native 语言基础之React ,敬请期待。


参考资料

前端开发者不得不知的ES6十大特性

React Native 相关JS和React基础

30分钟掌握ES6/ES2015核心内容

2018-12-25 15:59:12 baihailing 阅读数 78

参考文章:http://es6.ruanyifeng.com/#docs/style

.块级作用域

(1)let 取代var;

(2)全局常量和线程安全:

在let 和const之间,优先建议使用const,尤其是在全局环境,不应该设置变量,只应设置常量。

// bad
var a = 1, b = 2, c = 3;

// good
const a = 1;
const b = 2;
const c = 3;

// best
const [a, b, c] = [1, 2, 3];

2.字符串

静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。

// bad
const a = "foobar";
const b = 'foo' + a + 'bar';

// acceptable
const c = `foobar`;

// good
const a = 'foobar';
const b = `foo${a}bar`;

3.解构赋值

使用数组成员对变量赋值时,优先使用解构赋值。

const arr = [1,2,3];

//bad 
const first = arr[0];
const second = arr[1];

//good
const [first, second] = arr;

函数的参数如果是对象的成员,优先使用解构赋值。

//bad
function getFullName(user) {
 const firstName = user.firstName;
 const lastName = user.lastName;
}


//good
function getfullName(obj) {
 const {firstName,lastName } = obj;
}

//best
function getFullName({first, lastName}) {
}

如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值。这样便于以后添加返回值,以及更改返回值的顺序/

// bad
function processInput(input) {
  return [left, right, top, bottom];
}

// good
function processInput(input) {
  return { left, right, top, bottom };
}

const { left, right } = processInput(input);

4.对象

单行定义的对象,最后一个成员不以逗号结尾,多行定义的对象,最后一个成员以逗号结尾。

// bad
const a = { k1: v1, k2: v2, };
const b = {
  k1: v1,
  k2: v2
};

// good
const a = { k1: v1, k2: v2 };
const b = {
  k1: v1,
  k2: v2,
};

对象尽量静态化,一旦定义,就不得随意添加新的属性,如果添加属性不可避免,要使用Object.assign方法。

//bad 
const a = {};
a.x = 3;

//if reshape unavoidable
const a = {};
Object.assign(a,{x: 3});


//good
const a = {x: null};
a.x = 3;

如果对象的属性名是动态的,可以在创造对象的时候,使用属性表达式定义。

// bad
const obj = {
  id: 5,
  name: 'San Francisco',
};
obj[getKey('enabled')] = true;

// good
const obj = {
  id: 5,
  name: 'San Francisco',
  [getKey('enabled')]: true,
};

上面代码中,对象obj的最后一个属性名,需要计算得到。这时最好采用属性表达式,在新建obj的时候,将该属性与其他属性定义在一起。这样一来,所有属性就在一个地方定义了。

另外,对象的属性和方法,尽量采用简洁表达法,这样易于描述和书写。

var ref = 'some value';

//bad 
const atom = {
  ref: ref,
 
  value: 1,
  

  addValue: function(value) {
  return atom.value + value;
  },
};


//good
const atom = {
  ref,
 
  value: 1,
  

  addValue(value) {
   return atom.value + value;
  },
};

 

 

 

 

 

 

2017-03-13 09:24:00 weixin_33728268 阅读数 2

最近整理了一些ES5和ES6的写法对照表,希望大家以后读到ES5的代码,也能通过对照,在ES6下实现相同的功能,希望大家有用。

模块

引用

在ES5里,如果使用CommonJS标准,引入React包基本通过require进行,代码类似这样:

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

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

在ES6里,import写法更为标准

//ES6
import React, { 
    Component,
    PropTypes,
} from 'react';
import {
    Image,
    Text
} from 'react-native'

导出单个类

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

//ES5
var MyComponent = React.createClass({
    ...
});
module.exports = MyComponent;

在ES6里,通常用export default来实现相同的功能:

//ES6
export default class MyComponent extends Component{
    ...
}

引用的时候也类似:

//ES5
var MyComponent = require('./MyComponent');

//ES6
import MyComponent from './MyComponent';

注意导入和导出的写法必须配套,不能混用!

定义组件

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

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

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

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

给组件定义方法

从上面的例子里可以看到,给组件定义方法不再用 名字: function()的写法,而是直接用名字(),在方法的最后也不能有逗号了。

//ES5 
var Photo = React.createClass({
    componentWillMount: function(){

    },
    render: function() {
        return (
            <View>
                <Image source={this.props.source} />
            </View>
        );
    },
});
//ES6
class Photo extends Component {
    componentWillMount() {

    }
    render() {
        return (
            <View>
                <Image source={this.props.source} />
            </View>
        );
    }
}

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

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

//ES5 
var Video = React.createClass({
    getDefaultProps: function() {
        return {
            autoPlay: false,
            maxLoops: 10,
        };
    },
    propTypes: {
        autoPlay: React.PropTypes.bool.isRequired,
        maxLoops: React.PropTypes.number.isRequired,
        posterFrameSrc: React.PropTypes.string.isRequired,
        videoSrc: React.PropTypes.string.isRequired,
    },
    render: function() {
        return (
            <View>
              
            </View>
        );
    },
});

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

//ES6
class Video extends 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,
    };  // 注意这里有分号
    render() {
        return (
            <View>
            </View>
        );
    } // 注意这里既没有分号也没有逗号
}

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

//ES6
class Video extends Component {
    render() {
        return (
            <View>
            </View>
        );
    }
}
Video.defaultProps = {
    autoPlay: false,
    maxLoops: 10,
};
Video.propTypes = {
    autoPlay: React.PropTypes.bool.isRequired,
    maxLoops: React.PropTypes.number.isRequired,
    posterFrameSrc: React.PropTypes.string.isRequired,
    videoSrc: React.PropTypes.string.isRequired,
};

注意: 对React开发者而言,static成员在IE10及之前版本不能被继承,而在IE11和其它浏览器上可以,这有时候会带来一些问题。React Native开发者可以不用担心这个问题。

初始化STATE

ES5下情况类似,

//ES5 
var Video = React.createClass({
    getInitialState: function() {
        return {
            loopsRemaining: this.props.maxLoops,
        };
    },
})

ES6下,有两种写法:

//ES6
class Video extends Component {
    state = {
        loopsRemaining: this.props.maxLoops,
    }
}

不过我们推荐更易理解的在构造函数中初始化(这样你还可以根据需要做一些计算):

//ES6
class Video extends Component {
    constructor(props){
        super(props);
        this.state = {
            loopsRemaining: this.props.maxLoops,
        };
    }
}

把方法作为回调提供

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

//ES5
var PostInfo = React.createClass({
    handleOptionsButtonClick: function(e) {
        // Here, 'this' refers to the component instance.
        this.setState({showOptionsModal: 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 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 PauseMenu extends Component{
    componentWillMount(){
        AppStateIOS.addEventListener('change', this.onAppPaused.bind(this));
    }
    componentDidUnmount(){
        AppStateIOS.removeEventListener('change', this.onAppPaused.bind(this));
    }
    onAppPaused(event){
    }
}
// 正确的做法
class PauseMenu extends Component{
    constructor(props){
        super(props);
        this._onAppPaused = this.onAppPaused.bind(this);
    }
    componentWillMount(){
        AppStateIOS.addEventListener('change', this._onAppPaused);
    }
    componentDidUnmount(){
        AppStateIOS.removeEventListener('change', this._onAppPaused);
    }
    onAppPaused(event){
    }
}
// 正确的做法
class PauseMenu extends Component{
    componentWillMount(){
        AppStateIOS.addEventListener('change', this.onAppPaused);
    }
    componentDidUnmount(){
        AppStateIOS.removeEventListener('change', this.onAppPaused);
    }
    onAppPaused = (event) => {
        //把方法直接作为一个arrow function的属性来定义,初始化的时候就绑定好了this指针
    }
}

Mixins

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

var PureRenderMixin = require('react-addons-pure-render-mixin');
React.createClass({
  mixins: [PureRenderMixin],

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

然而现在官方已经不再打算在ES6里继续推行Mixin,应当尽快放弃Mixin的编写方式。

//Enhance.js
import { Component } from "React";

export var Enhance = ComposedComponent => class extends Component {
    constructor() {
        this.state = { data: null };
    }
    componentDidMount() {
        this.setState({ data: 'Hello' });
    }
    render() {
        return <ComposedComponent {...this.props} data={this.state.data} />;
    }
};
//HigherOrderComponent.js
import { Enhance } from "./Enhance";

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

export default Enhance(MyComponent); // Enhanced component

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

ES6+带来的其它好处

解构&属性延展

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

class AutoloadingPostsGrid extends Component {
    render() {
        const {
            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>
        );
    }
}

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

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

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

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

以后收集到就继续更新上去,方便学习语法

没有更多推荐了,返回首页