React入門教程

來源:互聯網
上載者:User
一、React安裝
1.使用React需引入三個庫:
react.min.js - React 的核心庫 react-dom.min.js - 提供與 DOM 相關的功能 babel.min.js/browser.min.js - Babel 可以將 ES6 代碼轉為 ES5 代碼,它內嵌了對 JSX 的支援。 2.使用 create-react-app 快速構建 React 開發環境
create-react-app 是來自於 Facebook,通過該命令我們無需配置就能快速構建 React 開發環境。
create-react-app 自動建立的項目是基於 Webpack + ES6 。
執行以下命令建立項目:
$ cnpm install -g create-react-app
$ create-react-app my-app
$ cd my-app/
$ npm start
二、HTML網頁模板
<!DOCTYPE html><html>  <head>    <script src="../build/react.js"></script>    <script src="../build/react-dom.js"></script>    <script src="../build/browser.min.js"></script>  </head>  <body>    <div id="example"></div>    <script type="text/babel">      // ** Our code goes here! **    </script>  </body></html>
註:Browser.js 的作用是將 JSX 文法轉為 JavaScript 文法。
$ babel src --out-dir build
上面命令可以將 src 子目錄的 js 檔案進行文法轉換,轉碼後的檔案全部放在 build 子目錄。
三、ReactDOM.render()
ReactDOM.render 是 React 的最基本方法,用於將模板轉為 HTML 語言,並插入指定的 DOM 節點。
ReactDOM.render(  <h1>Hello, world!</h1>,  document.getElementById('example'));
上面代碼將一個 h1 標題,插入 example 節點
四、JSX 文法
JSX 的文法允許 HTML 與 JavaScript 的混寫:
var names = ['Alice', 'Emily', 'Kate'];ReactDOM.render(  <div>  {    names.map(function (name) {      return <div>Hello, {name}!</div>    })  }  </div>,  document.getElementById('example'));
上面代碼體現了 JSX 的基本文法規則:遇到 HTML 標籤(以 < 開頭),就用 HTML 規則解析;遇到代碼塊(以 { 開頭),就用 JavaScript 規則解析。
JSX 允許直接在模板插入 JavaScript 變數。如果這個變數是一個數組,則會展開這個數組的所有成員:
var arr = [  <h1>Hello world!</h1>,  <h2>React is awesome</h2>,];ReactDOM.render(  <div>{arr}</div>,  document.getElementById('example'));
五、組件
React 允許將代碼封裝成組件(component),然後像插入普通 HTML 標籤一樣,在網頁中插入這個組件。
React.createClass 方法就用於產生一個組件類:
var HelloMessage = React.createClass({  render: function() {    return <h1>Hello {this.props.name}</h1>;  }});ReactDOM.render(  <HelloMessage name="John" />,  document.getElementById('example'));
上面代碼中,變數 HelloMessage 就是一個組件類。模板插入 <HelloMessage /> 時,會自動產生 HelloMessage 的一個執行個體。所有組件類都必須有自己的 render 方法,用於輸出組件。
注意:組件類的第一個字母必須大寫,否則會報錯。另外,組件類只能包含一個頂層標籤,否則也會報錯。
組件的用法與原生的 HTML 標籤完全一致,可以任意加入屬性,比如 <HelloMessage name="John"> ,就是 HelloMessage 組件加入一個 name 屬性,值為 John。組件的屬性可以在組件類的 this.props 對象上擷取,比如 name 屬性就可以通過 this.props.name 讀取。
注意:添加組件屬性時 class 屬性需要寫成 className ,for 屬性需要寫成 htmlFor ,這是因為 class 和 for 是 JavaScript 的保留字。
六、this.props.children
this.props 對象的屬性與組件的屬性一一對應,但是有一個例外,就是 this.props.children 屬性。它表示組件的所有子節點。
var NotesList = React.createClass({  render: function() {    return (      <ol>      {        React.Children.map(this.props.children, function (child) {          return <li>{child}</li>;        })      }      </ol>    );  }});ReactDOM.render(  <NotesList>    <span>hello</span>    <span>world</span>  </NotesList>,  document.body);
上面代碼的 NoteList 組件有兩個 span 子節點,它們都可以通過 this.props.children 讀取。
注意:this.props.children 的值有三種可能(如果當前組件沒有子節點,它就是 undefined ;如果有一個子節點,資料類型是 object ;如果有多個子節點,資料類型就是 array )。
React 提供一個工具方法 React.Children 來處理 this.props.children 。我們可以用 React.Children.map 來遍曆子節點,而不用擔心 this.props.children 的資料類型是 undefined 還是 object。
七、PropTypes
組件的屬性可以接受任意值,字串、對象、函數等等都可以。有時,我們需要一種機制,驗證別人使用組件時,提供的參數是否符合要求。
組件類的PropTypes屬性,就是用來驗證組件執行個體的屬性是否符合要求。
var MyTitle = React.createClass({  propTypes: {    title: React.PropTypes.string.isRequired,  },  render: function() {     return <h1> {this.props.title} </h1>;   }});
上面的Mytitle組件有一個title屬性。PropTypes 告訴 React,這個 title 屬性是必須的,而且它的值必須是字串。
此外,getDefaultProps 方法可以用來設定組件屬性的預設值。
var MyTitle = React.createClass({  getDefaultProps : function () {    return {      title : 'Hello World'    };  },  render: function() {     return <h1> {this.props.title} </h1>;   }});ReactDOM.render(  <MyTitle />,  document.body);
上面代碼會輸出"Hello World"。
八、擷取真實的DOM節點
組件並不是真實的 DOM 節點,而是存在於記憶體之中的一種資料結構,叫做虛擬 DOM (virtual DOM)。只有當它插入文檔以後,才會變成真實的 DOM 。根據 React 的設計,所有的 DOM 變動,都先在虛擬 DOM 上發生,然後再將實際發生變動的部分,反映在真實 DOM上,這種演算法叫做 DOM diff ,它可以極大提高網頁的效能表現。
但是,有時需要從組件擷取真實 DOM 的節點,這時就要用到 ref 屬性。
var MyComponent = React.createClass({  handleClick: function() {    this.refs.myTextInput.focus();  },  render: function() {    return (      <div>        <input type="text" ref="myTextInput" />        <input type="button" value="Focus the text input" onClick={this.handleClick} />      </div>    );  }});ReactDOM.render(  <MyComponent />,  document.getElementById('example'));
上面代碼中,組件 MyComponent 的子節點有一個文本輸入框,用於擷取使用者的輸入。這時就必須擷取真實的 DOM 節點,虛擬 DOM 是拿不到使用者輸入的。為了做到這一點,文本輸入框必須有一個 ref 屬性,然後 this.refs.[refName] 就會返回這個真實的 DOM 節點。
注意:由於 this.refs.[refName] 屬性擷取的是真實 DOM ,所以必須等到虛擬 DOM 插入文檔以後,才能使用這個屬性,否則會報錯。
九、this.state
組件免不了要與使用者互動,React 的一大創新,就是將組件看成是一個狀態機器,一開始有一個初始狀態,然後使用者互動,導致狀態變化,從而觸發重新渲染 UI。
var LikeButton = React.createClass({  getInitialState: function() {    return {liked: false};  },  handleClick: function(event) {    this.setState({liked: !this.state.liked});  },  render: function() {    var text = this.state.liked ? 'like' : 'haven\'t liked';    return (      <p onClick={this.handleClick}>        You {text} this. Click to toggle.      </p>    );  }});ReactDOM.render(  <LikeButton />,  document.getElementById('example'));
上面代碼是一個 LikeButton 組件,它的 getInitialState 方法用於定義初始狀態,也就是一個對象,這個對象可以通過 this.state 屬性讀取。當使用者點擊組件,導致狀態變化,this.setState 方法就修改狀態值,每次修改以後,自動調用 this.render 方法,再次渲染組件。
注意:由於 this.props 和 this.state 都用於描述組件的特性,可能會產生混淆。一個簡單的區分方法是,this.props 表示那些一旦定義,就不再改變的特性,而 this.state 是會隨著使用者互動而產生變化的特性。
十、表單
使用者在表單填入的內容,屬於使用者跟組件的互動,所以不能用 this.props 讀取。
var Input = React.createClass({  getInitialState: function() {    return {value: 'Hello!'};  },  handleChange: function(event) {    this.setState({value: event.target.value});  },  render: function () {    var value = this.state.value;    return (      <div>        <input type="text" value={value} onChange={this.handleChange} />        <p>{value}</p>      </div>    );  }});ReactDOM.render(<Input/>, document.body);
上面代碼中,文本輸入框的值,不能用 this.props.value 讀取,而要定義一個 onChange 事件的回呼函數,通過 event.target.value 讀取使用者輸入的值。textarea 元素、select元素、radio元素都屬於這種情況。
十一、組件的生命週期
組件的生命週期分成三個狀態:
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):組件判斷是否重新渲染時調用
var Hello = React.createClass({  getInitialState: function () {    return {      opacity: 1.0    };  },  componentDidMount: function () {    this.timer = setInterval(function () {      var opacity = this.state.opacity;      opacity -= .05;      if (opacity < 0.1) {        opacity = 1.0;      }      this.setState({        opacity: opacity      });    }.bind(this), 100);  },  render: function () {    return (      <div style={{opacity: this.state.opacity}}>        Hello {this.props.name}      </div>    );  }});ReactDOM.render(  <Hello name="world"/>,  document.body);
上面代碼在hello組件載入以後,通過 componentDidMount 方法設定一個定時器,每隔100毫秒,就重新設定組件的透明度,從而引發重新渲染。
注意:組件的style屬性的設定方式不能寫成style="opacity:{this.state.opacity};",而要寫成style={{opacity: this.state.opacity}},這是因為 React 組件樣式是一個對象,所以第一重大括弧表示這是 JavaScript 文法,第二重大括弧表示樣式對象。
十二、Ajax
組件的資料來源,通常是通過 Ajax 請求從伺服器擷取,可以使用 componentDidMount 方法設定 Ajax 請求,等到請求成功,再用 this.setState 方法重新渲染 UI。
var UserGist = React.createClass({  getInitialState: function() {    return {      username: '',      lastGistUrl: ''    };  },  componentDidMount: function() {    $.get(this.props.source, function(result) {      var lastGist = result[0];      if (this.isMounted()) {        this.setState({          username: lastGist.owner.login,          lastGistUrl: lastGist.html_url        });      }    }.bind(this));  },  render: function() {    return (      <div>        {this.state.username}'s last gist is        <a href={this.state.lastGistUrl}>here</a>.      </div>    );  }});ReactDOM.render(  <UserGist source="https://api.github.com/users/octocat/gists" />,  document.body);
我們也可以把一個Promise對象傳入組件:
ReactDOM.render(  <RepoList    promise={$.getJSON('https://api.github.com/search/repositories?q=javascript&sort=stars')}  />,  document.body);
上面代碼從Github的API抓取資料,然後將Promise對象作為屬性,傳給RepoList組件。
如果Promise對象正在抓取資料(pending狀態),組件顯示"正在載入";如果Promise對象報錯(rejected狀態),組件顯示報錯資訊;如果Promise對象抓取資料成功(fulfilled狀態),組件顯示擷取的資料。
var RepoList = React.createClass({  getInitialState: function() {    return { loading: true, error: null, data: null};  },  componentDidMount() {    this.props.promise.then(      value => this.setState({loading: false, data: value}),      error => this.setState({loading: false, error: error}));  },  render: function() {    if (this.state.loading) {      return <span>Loading...</span>;    }    else if (this.state.error !== null) {      return <span>Error: {this.state.error.message}</span>;    }    else {      var repos = this.state.data.items;      var repoList = repos.map(function (repo) {        return (          <li>            <a href={repo.html_url}>{repo.name}</a> ({repo.stargazers_count} stars) <br/> {repo.description}          </li>        );      });      return (        <main>          <h1>Most Popular JavaScript Projects in Github</h1>          <ol>{repoList}</ol>        </main>      );    }  }});
轉載自: 點擊開啟連結
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.