React入門例項參考阮一峰部落格

青衫無名發表於2018-06-01

React 可以在瀏覽器執行,也可以在伺服器執行。伺服器的用法與瀏覽器差別不大。

1 hello world程式

**開發環境**visual studio code和谷歌瀏覽器(谷歌瀏覽器翻牆安裝React Developer Tools)。

1.1 使用 React 開發新專案

前提安裝npm工具,Node版本 >= 6。 
在工作空間,執行以下命令:

1.  npm install -g create-react-app
2.  create-react-app my-app
3.  cd my-app
4.  npm start
  • 1
  • 2
  • 3
  • 4

然後開啟http:// localhost:3000 /檢視您的應用程式。

建立React App不處理後端邏輯或資料庫; 它只是建立一個前端構建管道,所以你可以將它用於任何你想要的後端。

當您準備部署到生產環境時,執行

npm run build
  • 1

將在build資料夾中建立應用程式的優化版本。將 src 子目錄的 js 檔案進行語法轉換,轉碼後的檔案全部放在 build 子目錄。

結果 
在當前資料夾內建立一個目錄。my-app 
在該目錄內,它將生成初始專案結構並安裝依賴項:

my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   └── favicon.ico
│   └── index.html
│   └── manifest.json
└── src
    └── App.css
    └── App.js
    └── App.test.js
    └── index.css
    └── index.js
    └── logo.svg
    └── registerServiceWorker.js
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

沒有配置或複雜的資料夾結構,只有構建應用程式所需的檔案。

安裝完成後,您可以開啟專案資料夾,編輯目錄、檔案開發自己的專案(如下面: 修改APP.js)。

如果您更改了程式碼,該頁面將自動重新載入。您將在控制檯中看到構建錯誤和lint警告。

1) APP.js檔案中編寫Hello world程式

APP.js原始碼:

import React, { Component } from `react`;

class App extends Component {
  render() {
    return (
      <div className="App">

          <h1 className="App-title">Hello World</h1>

      </div>
    );
  }
}

export default App;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

注意:元件類只能包含一個頂層標籤,否則也會報錯

1.2 執行現有React專案/框架

一般readme檔案中有說明,仔細閱讀。執行現有原始碼包的基本步驟 
1) 在專案的目錄安裝依賴

$ npm install
  • 1

2) 將src子目錄中的所有jsx檔案轉換為js檔案。

$ npm run build

  • 1
  • 2

3) 啟動http server

$ node server.js
  • 1

2 render()

render()是 React 的最基本方法用於將模板轉為 HTML 語言,並插入指定的 DOM 節點。 
例如:index.js中將App標籤,插入 root節點

ReactDOM.render(
    <App />,
document.getElementById(`root`)
);
  • 1
  • 2
  • 3
  • 4

3 JSX 語法

HTML 語言直接寫在 JavaScript 語言之中,不加任何引號,這就是 JSX 的語法,它允許 HTML 與 JavaScript 的混寫。 
demo2 
(專案index.js中修改import App from ‘./demo1’即可執行對應示例)

import React, { Component } from `react`;

var names = [`Alice`, `Emily`, `Kate`];

class App extends Component{
    render(){
        return(
            <div>
                {
                    names.map(function (name, index) {
                    return <div key={index}>Hello, {name}!</div>
                    })
                }
            </div>
        )
    };
}

export default App;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

JSX 的基本語法規則:遇到 HTML 標籤(以 < 開頭),就用 HTML 規則解析;遇到程式碼塊(以 { 開頭),就用 JavaScript 規則解析。 
JSX 允許直接在模板插入 JavaScript 變數。如果這個變數是一個陣列,則會展開這個陣列的所有成員。JSX 會把它的所有成員,新增到模板。 
demo03

import React, { Component } from `react`;

var arr = [
    <h1>Hello world!</h1>,
    <h2>React is awesome</h2>,
  ];

class App extends Component{
    render(){
        return(
            <div>
                <div>{arr}</div>
            </div>
        )
    };
}

export default App;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

4 元件

React 允許將程式碼封裝成元件(component),然後像插入普通 HTML 標籤一樣,在網頁中插入這個元件。class關鍵字用於生成一個元件類。 
demo04

import React, { Component } from `react`;

class App extends Component{
    render(){
        return(
            <div>
                 <HelloMessage name="pengwei" />,
            </div>
        )
    };
}

class HelloMessage extends Component{
    render() {
      return <h1>Hello {this.props.name}</h1>;
    }
  }

export default App;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

上面程式碼中,變數 HelloMessage 就是一個元件類。模板插入 時,會自動生成 HelloMessage 的一個例項(下文的”元件”都指元件類的例項)。所有元件類都必須有自己的 render 方法,用於輸出元件。

注意,元件類的第一個字母必須大寫,否則會報錯,比如HelloMessage不能寫成helloMessage。另外,元件類只能包含一個頂層標籤,否則也會報錯。

元件的用法與原生的 HTML 標籤完全一致,可以任意加入屬性,比如 ,就是 HelloMessage 元件加入一個 name 屬性,值為 John。元件的屬性可以在元件類的 this.props 物件上獲取,比如 name 屬性就可以通過 this.props.name 讀取。

注意,新增元件屬性, class 屬性需要寫成 className ,for 屬性需要寫成 htmlFor ,這是因為 class 和 for 是 JavaScript 的保留字。

5 this.props.children

this.props 物件的屬性與元件的屬性一一對應,但是有一個例外,就是 this.props.children 屬性,它表示元件的所有子節點。 
demo05

import React, { Component } from `react`;

class App extends Component{
    render(){
        return(
            <div>
                <Parent>
                    <span>hello</span>
                    <span>world</span>
                </Parent>
            </div>
        )
    };
}

class Parent extends Component{
    render(){
        return(
            <ol>
                {React.Children.map(this.props.children,function(child)
                    {return <li>{child}</li>;})}
            </ol>
        )
    };
}

export default App;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

注意, this.props.children 的值有三種可能:如果當前元件沒有子節點,它就是 undefined ;如果有一個子節點,資料型別是 object ;如果有多個子節點,資料型別就是 array 。所以,處理 this.props.children 的時候要小心。 
React 提供一個工具方法 React.Children 來處理 this.props.children 。我們可以用 React.Children.map 來遍歷子節點,而不用擔心 this.props.children 的資料型別

6 PropTypes和DefaultProps

元件的屬性可以接受任意值,字串、物件、函式等等都可以。有時,我們需要一種機制,驗證別人使用元件時,提供的引數是否符合要求。 
– PropTypes屬性,就是用來驗證元件例項的屬性是否符合要求。 
– DefaultProps 方法可以用來設定元件屬性的預設值。 
demo06

import React, { Component } from `react`;
import PropTypes from `prop-types`;

class App extends Component{
    render(){
        return(
            <div>
                 <DefaultMessage />
            </div>
        );
    };
}

class DefaultMessage extends Component{
    render() {
    return (<h1>Hello {this.props.name}</h1>);
    }
  }

DefaultMessage.propTypes = {
    name: PropTypes.string
};

DefaultMessage.defaultProps ={
      name : `World`
 }

export default App;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

7 獲取真實的DOM節點

元件並不是真實的 DOM 節點,而是存在於記憶體之中的一種資料結構,叫做虛擬 DOM (virtual DOM)。只有當它插入文件以後,才會變成真實的 DOM 。根據 React 的設計,所有的 DOM 變動,都先在虛擬 DOM 上發生,然後再將實際發生變動的部分,反映在真實 DOM上,這種演算法叫做 DOM diff ,它可以極大提高網頁的效能表現。 
但是,有時需要從元件獲取真實 DOM 的節點,這時就要用到 ref 屬性 
demo07

import React, { Component } from `react`;

class App extends Component{

    render(){
        return(
            <div>
                 <TrueDom />
            </div>
        );
    };
}

class TrueDom extends Component{
    constructor(props) {
        super(props);
        // This binding is necessary to make `this` work in the callback
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick() {
      this.refs.myTextInput.focus();
    };

    render() {
        return(
            <div>
                <input type="text" ref="myTextInput" />
                <input type="button" value="Focus the text input" onClick={this.handleClick} />
            </div>
        );
    };
  }

export default App;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

需要注意的是,由於 this.refs.[refName] 屬性獲取的是真實 DOM ,所以必須等到虛擬 DOM 插入文件以後,才能使用這個屬性,否則會報錯。上面程式碼中,通過為元件指定 Click 事件的回撥函式,確保了只有等到真實 DOM 發生 Click 事件之後,才會讀取 this.refs.[refName] 屬性。

8 this.state

react將元件看成是一個狀態機,一開始有一個初始狀態,然後使用者互動,導致狀態變化,從而觸發重新渲染 UI。 
由於 this.props 和 this.state 都用於描述元件的特性,可能會產生混淆。一個簡單的區分方法是,this.props 表示那些一旦定義,就不再改變的特性,而 this.state 是會隨著使用者互動而產生變化的特性 
demo08

import React, { Component } from `react`;

class App extends Component{
    render(){
        return(
            <div>
               <LikeButton/>
            </div>
        )
    };
}

class LikeButton extends Component{
    constructor(props) {
     super(props);
     this.state = {liked: false};
     // This binding is necessary to make `this` work in the callback
     this.handleClick = this.handleClick.bind(this);
   }  

     handleClick(event) {
       this.setState({liked: !this.state.liked});
     };
     render() {
       var text = this.state.liked ? `like` : `don`t liked`;
       return (
         <p onClick={this.handleClick}>
           You {text} this. Click to toggle.
         </p>
       );
     };
   }

export default App;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

9 表單

使用者在表單填入的內容,屬於使用者跟元件的互動,所以不能用 this.props 讀取 
demo9

import React, { Component } from `react`;


class App extends Component{
    render(){
        return(
            <div>
               <Input/>
            </div>
        )
    };
}


class Input extends Component{
    constructor(props) {
      super(props);
      this.state = {value: `Hello!`};
      // This binding is necessary to make `this` work in the callback
      this.handleChange = this.handleChange.bind(this);
    };

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

    render() {
      var value = this.state.value;
      return (
        <div>
          <input type="text" value={value} onChange={this.handleChange} />
          <p>{value}</p>
        </div>
      );
    };
  }

  export default App;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

上面程式碼中,文字輸入框的值,不能用 this.props.value 讀取,而要定義一個 onChange 事件的回撥函式,通過 event.target.value 讀取使用者輸入的值。

10 元件的生命週期

元件的生命週期分成三個狀態: 
– Mounting:已插入真實 DOM 
– Updating:正在被重新渲染 
– Unmounting:已移出真實 DOM

React 為每個狀態都提供了兩種處理函式,will 函式在進入狀態之前呼叫,did 函式在進入狀態之後呼叫,三種狀態共計五種處理函式: 
– componentWillMount() 
– componentDidMount() 
– componentWillUpdate(object nextProps, object nextState) 
– componentDidUpdate(object prevProps, object prevState) 
– componentWillUnmount()

此外,React 還提供兩種特殊狀態的處理函式: 
– componentWillReceiveProps(object nextProps):已載入元件收到新的引數時呼叫 
– shouldComponentUpdate(object nextProps, object nextState):元件判斷是否重新渲染時呼叫 
demo10

import React, { Component } from `react`;

class App extends Component{
    render(){
        return(
            <div>
               <ComponentLifestyle name = "pengwei"/>
            </div>
        )
    };
}


class ComponentLifestyle extends Component{
    constructor(props) {
        super(props);
        this.state = {opacity: 1.0};
    };

    componentWillMount() {
        this.timer = setInterval(function () {
        var opacity = this.state.opacity;
        var flag = this.state.flag;

        if(opacity >= 1||opacity<=0)
        {flag = !flag;}

        if (flag){
            opacity -= 0.02;
        }
        else{
            opacity += 0.02;
        }

        this.setState({
            opacity: opacity,
            flag: flag
        });
        }.bind(this), 100);
    };

    render() {
        return (
        <div style={{opacity: this.state.opacity}} flag = {true}>
            Hello {this.props.name}
        </div>
        );
    };
}

export default App;

原文釋出時間:2018年03月25日

本文來源CSDN部落格如需轉載請緊急聯絡作者


相關文章