React基礎再回顧

從16年夏天初學React,到17年正式投入到工做中使用,直到如今V16.2發版,React發生了巨大的變化,最近在工做中使用時遇到不少基礎不是很是清晰,藉此再讀 React官方文檔 【中文】

React核心的單向數據流、一切皆數據的state、不會改變的props,以及狀態提高等等常用便很少總結,須要的看官方文檔。html

JSX

JSX 本質只是爲 React.createElement(component, props, ...children)提供的語法糖!react

  • 1.React DOM 在渲染以前都被轉換成了字符串,它天生自帶防止 XSS 攻擊的屬性。
  • 2.Babel 轉譯器會把 JSX 轉換成一個名爲 React.createElement()的方法調用。在線babel編譯

如下兩段代碼等價(許多react的界面設計器經過這個原理,達到元數據轉化React元素,實現界面化編程!)
嵌套就是多個create方法的嵌套。express

function hello() {
  return <div className="red">Hello,<span>world!</span></div>;
}
"use strict";

function hello() {
  return React.createElement(
    "div",
    { className: "red" },
    "Hello,",
    React.createElement(
      "span",
      null,
      "world!"
    )
  );
}
  • 3.JSX中的屬性是能夠任何 {} 包裹的 JavaScript 表達式做爲一個屬性值,不能使用if和for。

須要循環和條件渲染可使用map、三目,或者使用if/for在jsx代碼以外!編程

//錯誤的!
class A extends React.Component {
  render() {
    return <div>{if(){}else{}}</div>;//原來還矇蔽的不知道爲何錯了0.0
  }
}

React.Component (組件)

建立組件的四種方式:詳情對比參見或者react官網數組

  • React.Component 方式
class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
  • ES5
var createReactClass = require('create-react-class');
var Greeting = createReactClass({
  render: function() {
    return <h1>Hello, {this.props.name}</h1>;
  }
});
//或者使用react
var Greeting = React.create({
  render: function() {
    return <h1>Hello, {this.props.name}</h1>;
  }
});
  • 函數式
const Button = ({
  day,
  increment
}) => {
  return (
    <div>
      <button onClick={increment}>Today is {day}</button>
    </div>
  )
}
  • PureComponet

大多數狀況下, 咱們使用PureComponent可以簡化咱們的代碼,而且提升性能,可是PureComponent的自動爲咱們添加的shouldComponentUpate函數,只是對props和state進行淺比較(shadow comparison),當props或者state自己是嵌套對象或數組等時,淺比較並不能獲得預期的結果,這會致使實際的props和state發生了變化,但組件卻沒有更新的問題。固然仍是有解決的方法的,因此建議仍是少用。babel

事件處理

事件綁定的四種方法:推薦使用第一第二種。dom

class Toggle extends React.Component {
  constructor(props) {
  {...}
  //方法一必須在這裏綁定
    this.handleClick1 = this.handleClick.bind(this);
  }
  handleClick1() {
    this...
  }
  //方法二使用【屬性初始化器語法】【須要開啓babel stage-0以上】
  handleClick2=()=> {
    this...
  }
  render() {
    return (
    <div>
      <button onClick={this.handleClick1}></button>
      <button onClick={this.handleClick2}></button>
      //方法三在使用時綁定
      <button onClick={this.handleClick1.bind(this)}></button>
      //方法四在回調函數中使用 箭頭函數
      /**
      渲染的時候都會建立一個不一樣的回調函數。在大多數狀況下,這沒有問題。然而若是這個回調函數做爲一個屬性值傳入低階組件,這些組件可能會進行額外的從新渲染。咱們一般建議在構造函數中綁定或使用屬性初始化器語法來避免這類性能問題。
      **/
      <button onClick={(e) => this.handleClick1(e)}></button>
      
    </div>
    );
  }
}

組合 vs 繼承

在React中不推薦使用繼承,不推薦繼承自定義Component。函數

//不推薦使用
class Parent extends React.Component {
  render() {
    return <div>...</div>;
  }
}
class A extends Parent {
  render() {
    return <div>...</div>;
  }
}
//推薦使用
class A extends React.Component {
  render() {
    return <Parent>...</Parent>;
  }
}

不使用 ES6

  • Component || create
  • defaultProps || getDefaultProps
  • constructor state || getInitialState
  • this bind || 不須要
class Greeting extends React.Component {
constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
    this.handleClick = this.handleClick.bind(this);
  }
   handleClick() {
    alert(this.state.message);
  }
  render() {
    return <h1 onClick={this.handleClick}>Hello, {this.props.name}</h1>;
  }
}
Greeting.defaultProps = {
  name: 'Mary'
};
var createReactClass = require('create-react-class');
var Greeting = createReactClass({
 getInitialState: function() {
    return {count: this.props.initialCount};
  },
getDefaultProps: function() {
    return {
      name: 'Mary'
    };
  },
   handleClick: function() {
    alert(this.state.message);
  },
  render: function() {
  //組件中的方法會自動綁定至實例,不須要像上面那樣加 .bind(this)
    return <h1 onClick={this.handleClick}>Hello, {this.props.name}</h1>;
  }
});

Refs

  1. 若是能夠經過聲明式實現,則儘可能避免使用 refs。
  2. 不能在函數式組件上使用 ref 屬性,由於它們沒有實例
  3. 舊版 API:String 類型的 Refs,存在問題,可能會在將來移除,不推薦使用。
  4. 對父組件暴露refs,在父元素拿子元素
function CustomTextInput(props) {
  return (
    <div>
      <input ref={props.inputRef} />
    </div>
  );
}

class Parent extends React.Component {
//this.inputElement 就是CustomTextInput中的input
  render() {
    return (
      <CustomTextInput
        inputRef={el => this.inputElement = el}
      />
    );
  }
}

ReactDOM

獲取一個DOM除了refs還有更加簡單粗暴的方法findDOMNode
findDOMNode 是用於操做底層DOM節點的備用方案。使用它的優先級比refs更低!!
findDOMNode 只對掛載過的組件有效。
findDOMNode 不能用於函數式的組件中。性能

import ReactDOM from 'react-dom';
ReactDOM.render(
  element,
  container,
  [callback]//鮮爲人知的第三個參數!!
)
ReactDOM.unmountComponentAtNode(container)
ReactDOM.findDOMNode(component)

不經常使用的新發現

  • 空的 JSX 標籤Fragments <></>或者<React.Fragment></React.Fragment>
  • 與運算符 && true && expression 老是返回 expression,而 false && expression 老是返回 false。
  • 阻止組件渲染經常使用null組件的 render 方法返回 null 並不會影響該組件生命週期方法的回調。例如,componentWillUpdate 和 componentDidUpdate 依然能夠被調用。

### 高階組件HOC 使用高階組件(HOC)解決交叉問題ui

相關文章
相關標籤/搜索