React&ES6

1.class

ES6 提供了更接近傳統語言的寫法,引入了 Class(類)這個概念,作爲對象的模板。通過class關鍵字,可以定義類。
基本上,ES6 的class可以看作只是一個語法糖,它的絕大部分功能,ES5 都可以做到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已

特點

1.類的所有方法都定義在類的prototype屬性上面

class Point {
  constructor() {
    // ...
  }
}
==
Point.prototype = {
  constructor() {},
};

2.Point.prototype.constructor === Point // true
3.定義“類”的方法的時候,前面不需要加上function這個關鍵字,直接把函數定義放進去了就可以了
4.類不存在變量提升(hoist),這一點與 ES5 完全不同。
5.類的方法內部如果含有this,它默認指向類的實例
6.如果在一個方法前,加上static關鍵字,就表示該方法不會被實例繼承,而是直接通過類來調用,這就稱爲“靜 態方法”。
7.寫法

ES5寫法

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);

ES6

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

2.constructor( )——構造方法

這是ES6對類的默認方法,通過 new 命令生成對象實例時自動調用該方法。並且,該方法是類中必須有的,如果沒有顯示定義,則會默認添加空的constructor( )方法。

1.constructor方法默認返回實例對象(即this)

 class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}
point.hasOwnProperty('x') // true

2.super( ) ——繼承

在class方法中,繼承是使用 extends 關鍵字來實現的。子類 必須 在 constructor( )調用
 super( )方法,否則新建實例時會報錯。
在 constructor 中必須調用 super 方法,因爲子類沒有自己的 this 對象,而是繼承父類的 this 對象
,然後對其進行加工,而 super 就代表了父類的構造函數。super 雖然代表了父類 A 的構造函數,
但是返回的是子類 B 的實例,即 super 內部的 this 指的是 B,因此 super() 在這裏相當於 
A.prototype.constructor.call(this, props)。

class A {}
class B extends A {
  constructor() {
    super();  // ES6 要求,子類的構造函數必須執行一次 super 函數,否則會報錯。
  }
}

3.如果你在constructor中要使用this.props,就必須給super加參數:super(props);

3.ref 和 React.js 中的 DOM 操作

順帶一提的是,其實可以給組件標籤也加上 ref

 <input ref={(input) => this.input = input} />//input爲獲取的節點

4.react組件可內嵌組件或者節點原理

嵌套的結構在組件內部都可以通過 props.children 獲取到
class Card extends Component {
  render () {
    return (
      <div className='Card'>
        <div className='0'>
          {this.props.children[0]}
        </div>
        <div className='1'>
          {this.props.children[1]}
        </div>
      </div>
    )
  }
}
ReactDOM.render(
  <Card>
    <div>children[0]</div>
    <div>children[1]</div>
  </Card>,
  document.getElementById('root')
)

5.默認配置 defaultProps&&給組件的配置參數加上類型驗證

class LikeButton extends Component {
  static defaultProps = {
    likedText: '取消',
    unlikedText: '點贊'
  }
static propTypes = {
    comment: PropTypes.object//const { comment } = this.props
  }
static propTypes = {
  comment: PropTypes.object.isRequired
}
}

6.react中bind(this)的理解

bind返回值是由指定的this值和初始化參數改造的原函數拷貝
在JSX中傳遞的事件不是一個字符串,而是一個函數(如:onClick={this.handleClick}),此時onClick即是中間變量,所以處理函數中的this指向會丟失。解決這個問題就是給調用函數時bind(this),從而使得無論事件處理函數如何傳遞,this指向都是當前實例化對象。
當然,如果不想使用bind(this),我們可以在聲明函數時使用箭頭函數將函數內容返回給一個變量,並在調用時直接使用this.變量名即可
1
<button onClick={this.handleClick.bind(this)}>有bind點擊一下</button>
2
constructor(props) {
        super(props);
        this.state = {

        };
        this.handleClick=this.handleClick.bind(this)
    }
3
<button onClick={()=>{this.handleClick()}>

7.高階組件

高階組件是一個函數(而不是組件),它接受一個組件作爲參數,返回一個新的組件。這個新的組件會使用你傳給它的組件作爲子組件
import React, { Component } from 'react'

export default (WrappedComponent, name) => {
  class NewComponent extends Component {
    constructor () {
      super()
      this.state = { data: null }
    }

    componentWillMount () {
      let data = localStorage.getItem(name)
      this.setState({ data })
    }

    render () {
      return <WrappedComponent data={this.state.data} />
    }
  }
  return NewComponent
}
import wrapWithLoadData from './wrapWithLoadData'

class InputWithUserName extends Component {
  render () {
    return <input value={this.props.data} />
  }
}

InputWithUserName = wrapWithLoadData(InputWithUserName, 'username')
export default InputWithUserName

8.export&&import

模塊功能主要由兩個命令構成:export和import。export命令用於規定模塊的對外接口,import命令用於輸入其他模塊提供的功能。一個模塊就是一個獨立的文件。該文件內部的所有變量,外部無法獲取。如果你希望外部能夠讀取模塊內部的某個變量,就必須使用export關鍵字輸出該變量

1.export命令規定的是對外的接口,必須與模塊內部的變量建立一一對應關係
2.export語句輸出的接口,與其對應的值是動態綁定關係,即通過該接口,可以取到模塊內部實時的值
3.注意輸出時{}的使用表明其是一個接口,不用則爲值會報錯

//export var year = 1958;
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
----------
// 報錯
export 1;
// 報錯
var m = 1;
export m;
----------
// 寫法一
export var m = 1;
// 寫法二
var m = 1;
export {m};
// 寫法三
var n = 1;
export {n as m};
//函數
function f() {}
export {f};

4.import命令接受一對大括號,裏面指定要從其他模塊導入的變量名。大括號裏面的變量名,必須與被導入模塊(profile.js)對外接口的名稱相同
5.如果想爲輸入的變量重新取一個名字,import命令要使用as關鍵字,將輸入的變量重命名
6.import命令輸入的變量都是隻讀的,因爲它的本質是輸入接口。也就是說,不允許在加載模塊的腳本里面,改寫
接口
7.注意,import命令具有提升效果,會提升到整個模塊的頭部,首先執行
8.import是靜態執行,所以不能使用表達式和變量

import { lastName as surname } from './profile.js';
import {myMethod} from 'util';//util是模塊文件名,必須通過配置,告訴引擎怎麼取到這個模塊
import 'lodash';//import語句會執行所加載的模塊

9.模塊的整體加載

除了指定加載某個輸出值,還可以使用整體加載,即用星號(*)指定一個對象,所有輸出值都加載在這個對象上面。
// circle.js

export function area(radius) {
  return Math.PI * radius * radius;
}

export function circumference(radius) {
  return 2 * Math.PI * radius;
}
import * as circle from './circle';

console.log('圓面積:' + circle.area(4));
console.log('圓周長:' + circle.circumference(14));

10.export default命令,爲模塊指定默認輸出

// export-default.js
export default function () {
  console.log('foo');
}

// import-default.js
import customName from './export-default';
customName(); // 'foo'

1.使用export default時,對應的import語句不需要使用大括號

// 第一組
export default function crc32() { // 輸出
  // ...
}
import crc32 from 'crc32'; // 輸入
// 第二組
export function crc32() { // 輸出
  // ...
};
import {crc32} from 'crc32'; // 輸入
//結合使用
import _, { each, forEach } from 'lodash';

2.export default命令其實只是輸出一個叫做default的變量,所以它後面不能跟變量聲明語句

// 正確
export var a = 1;
// 正確
var a = 1;
export default a;
// 錯誤
export default var a = 1;

11.解構賦值

本質上,這種寫法屬於“模式匹配”,只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值。下面是一些使用嵌套數組進行解構的例子
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [x, , y] = [1, 2, 3];
x // 1
y // 3

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

1.如果等號的右邊不是數組(或者嚴格地說,不是可遍歷的結構,參見《Iterator》一章),那麼將會報錯

// 報錯
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;

2.解構賦值允許指定默認值

let [foo = true] = [];
foo // true

let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

3.解構不僅可以用於數組,還可以用於對象

//簡易模型
let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined
//基本模型
var robotA = { name: "Bender" }; 
var robotB = { name: "Flexo" }; 
var { name: nameA } = robotA; 
var { name: nameB } = robotB;
nameA//"Bender"
nameB//"Flexo"
//多重解構
const node = {
  loc: {
    start: {
      line: 1,
      column: 5
    }
  }
};

let { loc, loc: { start }, loc: { start: { line }} } = node;
line // 1
loc  // Object {start: Object}
start // Object {line: 1, column: 5}
//默認值
var {x, y = 5} = {x: 1};
x // 1
y // 5
var { message: msg = "Something went wrong" } = {};
//JavaScript 引擎會將{x}理解成一個代碼塊,從而發生語法錯誤
//只有不將大括號寫在行首,避免 JavaScript 將其解釋爲代碼塊,才能解決這個問題
let x;
({x} = {x: 1});
//字符解構
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

12箭頭函數

箭頭函數沒有 this,所以需要通過查找作用域鏈來確定 this 的值。這就意味着如果箭頭函數被非箭頭函數包含,this 綁定的就是最近一層非箭頭函數的 this。
沒有 arguments
不能通過 new 關鍵字調用
沒有原型
沒有 super
格式1:多個參數
(param1, param2, …, paramN) => { statements }
// statements應該有return 語句 
(param1, param2, …, paramN) => expression 
//相當於 return expression

格式2:一個參數
 (singleParam) => { statements } 
singleParam => { statements } //可以去掉括號

格式3:沒有參數
() => { statements }

格式4:返回對象
params => ({foo: bar}) 

格式5:支持擴展符號
(param1, param2, ...rest) => { statements } 

格式6:支持默認值
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements } 

格式7:支持解構賦值
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; f(); // 6
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章