React學習文檔閱讀(一)

JSX

JSX 防注入攻擊

你能夠放心地在 JSX 當中使用用戶輸入,React DOM 在渲染以前默認會 過濾 全部傳入的值。它能夠確保你的應用不會被注入攻擊。全部的內容在渲染以前都被轉換成了字符串。這樣能夠有效地防止 XSS(跨站腳本) 攻擊。html

JSX 表明 Objects

Babel 轉譯器會把 JSX 轉換成一個名爲 React.createElement() 的方法調用。react

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
複製代碼

等價es6

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);
複製代碼

React.createElement() 這個方法首先會進行一些避免bug的檢查,以後會返回一個相似下面例子的對象:數組

// 注意: 如下示例是簡化過的(不表明在 React 源碼中是這樣)
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world'
  }
};
複製代碼

這樣的對象被稱爲 「React 元素」。它表明全部你在屏幕上看到的東西。React 經過讀取這些對象來構建 DOM 並保持數據內容一致。瀏覽器

元素渲染

與瀏覽器的 DOM 元素不一樣,React 當中的元素事實上是普通的對象,(也就是html標籤+內容)React DOM 能夠確保 瀏覽器 DOM 的數據內容與 React 元素保持一致。bash

const element = <h1>hello</h1>;
複製代碼

要將React元素渲染到根DOM節點中,咱們經過把它們都傳遞給 ReactDOM.render() 的方法來將其渲染到頁面上:dom

const element = <h1>hello</h1>;
ReactDOM.render(element,document.getElementById('root'));
複製代碼

更新元素渲染

React 元素都是不可變的。當元素被建立以後,你是沒法改變其內容或屬性的.一個元素就好像是動畫裏的一幀,它表明應用界面在某一時間點的樣子。異步

組件 & Props

組件能夠將UI切分紅一些獨立的、可複用的部件,這樣你就只需專一於構建每個單獨的部件。函數

組件從概念上看就像是函數,它能夠接收任意的輸入值(稱之爲「props」),並返回一個須要在頁面上展現的React元素。動畫

函數/es6類 定義組件

函數

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
複製代碼

es6類繼承

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
複製代碼

組件渲染

React元素也能夠是用戶自定義的組件: 例如,這段代碼會在頁面上渲染出」Hello,Sara」:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);
複製代碼

過程:一、咱們對<Welcome name="Sara" ,/>元素調用了ReactDOM.render()方法。

二、React將{name: 'Sara'}做爲props傳入並調用Welcome組件。

三、Welcome組件將<h1,>Hello, Sara</h1,>元素做爲結果返回。

四、React DOM將DOM更新爲<h1,>Hello, Sara</h1,>。

組件名稱必須以大寫字母開頭。

例如,<div,> 表示一個DOM標籤,但 <Welcome,> 表示一個組件,而且在使用該組件時你必須定義或引入它。

組件的返回值只能有一個根元素。這也是咱們要用一個<div,>來包裹全部<Welcome ,/>元素的緣由。

State & 生命週期

狀態(state)

定義爲的組件有一些額外的特性。局部狀態就是如此:只能用於類的一個功能。

狀態與屬性十分類似,可是狀態是私有的,徹底受控於當前組件。

將函數轉換爲類

你能夠經過5個步驟將函數組件 Clock 轉換爲類

一、建立一個名稱擴展爲 React.Component 的ES6 類

二、建立一個叫作render()的空方法

三、將函數體移動到 render() 方法中

四、在 render() 方法中,使用 this.props 替換 props

五、刪除剩餘的空函數聲明

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
複製代碼

Clock 如今被定義爲一個類而不僅是一個函數

使用類就容許咱們使用其它特性,例如局部狀態、生命週期鉤子

爲一個類添加局部狀態

咱們會通過3個步驟將 date 從屬性移動到狀態中

一、在 render() 方法中使用 this.state.date 替代 this.props.date

2.添加一個類構造函數來初始化狀態 this.state

3.從 元素移除 date 屬性: 代碼以下

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
複製代碼

將生命週期方法添加到類中

咱們能夠在組件類上聲明特殊的方法,當組件掛載或卸載時,來運行一些代碼:

componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }   //當組件輸出到 DOM 後會執行 componentDidMount() 鉤子,
      //這是一個創建定時器的好地方:

    componentWillUnmount() {
    clearInterval(this.timerID);
  } //咱們將在 componentWillUnmount()生命週期鉤子中卸載計時器:
複製代碼

最後,咱們實現了每秒鐘執行的 tick() 方法。

它將使用 this.setState() 來更新組件局部狀態:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }
!!!!
  tick() {
    this.setState({
      date: new Date()
    });
  }//setState() 來調度UI更新。
  //經過調用 setState() ,React 知道狀態已經改變,
  //並再次調用 render() 方法來肯定屏幕上應當顯示什麼。
!!!!
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
複製代碼

讓咱們快速回顧一下發生了什麼以及調用方法的順序:

一、當 被傳遞給 ReactDOM.render() 時,React 調用 Clock 組件的構造函數。 因爲 Clock 須要顯示當前時間,因此使用包含當前時間的對象來初始化 this.state 。 咱們稍後會更新此狀態。

2.React 而後調用 Clock 組件的 render() 方法。這是 React 瞭解屏幕上應該顯示什麼內容,而後 React 更新 DOM 以匹配 Clock 的渲染輸出。

3.當 Clock 的輸出插入到 DOM 中時,React 調用 componentDidMount() 生命週期鉤子。 在其中,Clock 組件要求瀏覽器設置一個定時器,每秒鐘調用一次 tick()。

4.瀏覽器每秒鐘調用 tick() 方法。 在其中,Clock 組件經過使用包含當前時間的對象調用 setState() 來調度UI更新。 經過調用 setState() ,React 知道狀態已經改變,並再次調用 render() 方法來肯定屏幕上應當顯示什麼。 這一次,render() 方法中的 this.state.date 將不一樣,因此渲染輸出將包含更新的時間,並相應地更新DOM。

5.一旦Clock組件被從DOM中移除,React會調用componentWillUnmount()這個鉤子函數,定時器也就會被清除。

正確地使用狀態

關於 setState() 這裏有三件事情須要知道

1.不要直接更新狀態

// Wrong 錯誤!!
this.state.comment = 'Hello';
應當使用 setState():

// Correct
this.setState({comment: 'Hello'});
複製代碼

構造函數是惟一可以初始化this.state的地方。

2.狀態更新多是異步的

由於 this.props 和 this.state 多是異步更新的,你不該該依靠它們的值來計算下一個狀態。

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});
複製代碼

要修復它,請使用第二種形式的 setState() 來接受一個函數而不是一個對象。 該函數將接收先前的狀態做爲第一個參數, 將這次更新被應用時的props作爲第二個參數:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));
複製代碼

三、狀態更新合併

數據自頂向下流動

父組件或子組件都不能知道某個組件是有狀態仍是無狀態,而且它們不該該關心某組件是被定義爲一個函數仍是一個類。

這就是爲何狀態一般被稱爲局部或封裝。 除了擁有並設置它的組件外,其它組件不可訪問。

事件處理

react和dom的很類似,可是有一些語法的不一樣

React事件綁定屬性的命名採用駝峯式寫法,而不是小寫。

若是採用 JSX 的語法你須要傳入一個函數做爲事件處理函數,而不是一個字符串(DOM元素的寫法) eg::: 傳統的 HTML:

<button onclick="activateLasers()">
  Activate Lasers
</button>
複製代碼

React 中稍稍有點不一樣:

<button onClick={activateLasers}>
  Activate Lasers
</button>
複製代碼

使用 React 的時候你不須要使用 addEventListener 爲一個已建立的 DOM元素添加監聽器。你僅僅須要在這個元素初始渲染的時候提供一個監聽器。

表單

受控組件

使用」受控組件」,每一個狀態的改變都有一個與之相關的處理函數。這樣就能夠直接修改或驗證用戶輸入。例如,咱們若是想限制輸入所有是大寫字母,咱們能夠將handleChange 寫爲以下:

handleChange(event) {
  this.setState({value: event.target.value.toUpperCase()});
}
複製代碼

textarea 標籤

在React中,<textarea,>會用value屬性來代替。這樣的話,表單中的<textarea,> 很是相似於使用單行輸入的表單:

class EssayForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: 'Please write an essay about your favorite DOM element.'
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('An essay was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <textarea value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}
複製代碼

注意this.state.value是在構造函數中初始化,這樣文本區域就能獲取到其中的文本。

select 標籤

請注意,Coconut選項最初因爲selected屬性是被選中的。在React中,並不使用以前的selected屬性,而在根select標籤上用value屬性來表示選中項。這在受控組件中更爲方便,由於你只須要在一個地方來更新組件。例如:

構造函數中
this.state = {value: 'coconut'};
類中
handleChange(event) {
    this.setState({value: event.target.value});
  }
  render return中
    <select value={this.state.value} onChange={this.handleChange}>
複製代碼
相關文章
相關標籤/搜索