国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項超值服

開通VIP
React 入門實例教程

現(xiàn)在最熱門的前端框架,毫無疑問是 React

上周,基于 React 的 React Native 發(fā)布,結(jié)果一天之內(nèi),就獲得了 5000 顆星,受矚目程度可見一斑。

React 起源于 Facebook 的內(nèi)部項目,因為該公司對市場上所有 JavaScript MVC 框架,都不滿意,就決定自己寫一套,用來架設(shè) Instagram 的網(wǎng)站。做出來以后,發(fā)現(xiàn)這套東西很好用,就在2013年5月開源了。

由于 React 的設(shè)計思想極其獨(dú)特,屬于革命性創(chuàng)新,性能出眾,代碼邏輯卻非常簡單。所以,越來越多的人開始關(guān)注和使用,認(rèn)為它可能是將來 Web 開發(fā)的主流工具。

這個項目本身也越滾越大,從最早的UI引擎變成了一整套前后端通吃的 Web App 解決方案。衍生的 React Native 項目,目標(biāo)更是宏偉,希望用寫 Web App 的方式去寫 Native App。如果能夠?qū)崿F(xiàn),整個互聯(lián)網(wǎng)行業(yè)都會被顛覆,因為同一組人只需要寫一次 UI ,就能同時運(yùn)行在服務(wù)器、瀏覽器和手機(jī)(參見《也許,DOM 不是答案》)。

既然 React 這么熱門,看上去充滿希望,當(dāng)然應(yīng)該好好學(xué)一下。從技術(shù)角度,可以滿足好奇心,提高技術(shù)水平;從職業(yè)角度,有利于求職和晉升,有利于參與潛力大的項目。但是,好的 React 教程卻不容易找到,這一方面因為這項技術(shù)太新,剛剛開始走紅,大家都沒有經(jīng)驗,還在摸索之中;另一方面因為 React 本身還在不斷變動,API 一直在調(diào)整,至今沒發(fā)布1.0版。

我學(xué)習(xí) React 時,就很苦惱。有的教程討論一些細(xì)節(jié)問題,對入門沒幫助;有的教程寫得不錯,但比較短,無助于看清全貌。我斷斷續(xù)續(xù)學(xué)了幾個月,看過二十幾篇教程,在這個過程中,將對自己有幫助的 Demo 都收集下來,做成了一個庫 React Demos 。

下面,我就根據(jù)這個庫,寫一篇全面又易懂的 React 入門教程。你只需要跟著每一個 Demo 做一遍,就能初步掌握 React 。當(dāng)然,前提是你必須擁有基本 JavaScript 和 DOM 知識,但是你讀完就會發(fā)現(xiàn),React 所要求的預(yù)備知識真的很少。

零、安裝

React 的安裝包,可以到官網(wǎng)下載。不過,React Demos 已經(jīng)自帶 React 源碼,不用另外安裝,只需把這個庫拷貝到你的硬盤就行了。

$ git clone git@github.com:ruanyf/react-demos.git

如果你沒安裝 git, 那就直接下載 zip 壓縮包。

下面要講解的10個例子在各個 Demo 子目錄,每個目錄都有一個 index.html 文件,在瀏覽器打開這個文件(大多數(shù)情況下雙擊即可),就能立刻看到效果。

需要說明的是,React 可以在瀏覽器運(yùn)行,也可以在服務(wù)器運(yùn)行,但是本教程只涉及瀏覽器。一方面是為了盡量保持簡單,另一方面 React 的語法是一致的,服務(wù)器的用法與瀏覽器差別不大。Demo11 是服務(wù)器首屏渲染的例子,有興趣的朋友可以自己去看源碼。

一、HTML 模板

使用 React 的網(wǎng)頁源碼,結(jié)構(gòu)大致如下。

<!DOCTYPE html><html>  <head>    <script src="../build/react.js"></script>    <script src="../build/JSXTransformer.js"></script>  </head>  <body>    <div id="example"></div>    <script type="text/jsx">      // ** Our code goes here! **    </script>  </body></html>

上面代碼有兩個地方需要注意。首先,最后一個 script 標(biāo)簽的 type 屬性為 text/jsx 。這是因為 React 獨(dú)有的 JSX 語法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/jsx" 。

其次,React 提供兩個庫: react.js 和 JSXTransformer.js ,它們必須首先加載。其中,JSXTransformer.js 的作用是將 JSX 語法轉(zhuǎn)為 JavaScript 語法。這一步很消耗時間,實際上線的時候,應(yīng)該將它放到服務(wù)器完成。

$ jsx src/ build/

上面命令可以將 src 子目錄的 js 文件進(jìn)行語法轉(zhuǎn)換,轉(zhuǎn)碼后的文件全部放在 build 子目錄。

二、React.render()

React.render 是 React 的最基本方法,用于將模板轉(zhuǎn)為 HTML 語言,并插入指定的 DOM 節(jié)點(diǎn)。

React.render(  <h1>Hello, world!</h1>,  document.getElementById('example'));

上面代碼將一個 h1 標(biāo)題,插入 example 節(jié)點(diǎn)(查看 demo01),運(yùn)行結(jié)果如下。

三、JSX 語法

上一節(jié)的代碼, HTML 語言直接寫在 JavaScript 語言之中,不加任何引號,這就是 JSX 的語法,它允許 HTML 與 JavaScript 的混寫(查看 Demo02 )。

var names = ['Alice', 'Emily', 'Kate'];React.render(  <div>  {    names.map(function (name) {      return <div>Hello, {name}!</div>    })  }  </div>,  document.getElementById('example'));

上面代碼體現(xiàn)了 JSX 的基本語法規(guī)則:遇到 HTML 標(biāo)簽(以 < 開頭),就用 HTML 規(guī)則解析;遇到代碼塊(以 { 開頭),就用 JavaScript 規(guī)則解析。上面代碼的運(yùn)行結(jié)果如下。

JSX 允許直接在模板插入 JavaScript 變量。如果這個變量是一個數(shù)組,則會展開這個數(shù)組的所有成員(查看 demo03 )。

var arr = [  <h1>Hello world!</h1>,  <h2>React is awesome</h2>,];React.render(  <div>{arr}</div>,  document.getElementById('example'));

上面代碼的arr變量是一個數(shù)組,結(jié)果 JSX 會把它的所有成員,添加到模板,運(yùn)行結(jié)果如下。

四、組件

React 允許將代碼封裝成組件(component),然后像插入普通 HTML 標(biāo)簽一樣,在網(wǎng)頁中插入這個組件。React.createClass 方法就用于生成一個組件類(查看 demo04)。

var HelloMessage = React.createClass({  render: function() {    return <h1>Hello {this.props.name}</h1>;  }});React.render(  <HelloMessage name="John" />,  document.getElementById('example'));

上面代碼中,變量 HelloMessage 就是一個組件類。模板插入 <HelloMessage /> 時,會自動生成 HelloMessage 的一個實例(下文的"組件"都指組件類的實例)。所有組件類都必須有自己的 render 方法,用于輸出組件。

組件的用法與原生的 HTML 標(biāo)簽完全一致,可以任意加入屬性,比如 <HelloMessage name="John" /> ,就是 HelloMessage 組件加入一個 name 屬性,值為 John。組件的屬性可以在組件類的 this.props 對象上獲取,比如 name 屬性就可以通過 this.props.name 讀取。上面代碼的運(yùn)行結(jié)果如下。

添加組件屬性,有一個地方需要注意,就是 class 屬性需要寫成 className ,for 屬性需要寫成 htmlFor ,這是因為 class 和 for 是 JavaScript 的保留字。

五、this.props.children

this.props 對象的屬性與組件的屬性一一對應(yīng),但是有一個例外,就是 this.props.children 屬性。它表示組件的所有子節(jié)點(diǎn)(查看 demo05)。

var NotesList = React.createClass({  render: function() {    return (      <ol>      {        this.props.children.map(function (child) {          return <li>{child}</li>        })      }      </ol>    );  }});React.render(  <NotesList>    <span>hello</span>    <span>world</span>  </NotesList>,  document.body);

上面代碼的 NoteList 組件有兩個 span 子節(jié)點(diǎn),它們都可以通過 this.props.children 讀取,運(yùn)行結(jié)果如下。

這里需要注意,只有當(dāng)子節(jié)點(diǎn)多余1個時,this.props.children 才是一個數(shù)組,否則是不能用 map 方法的, 會報錯。

六、React.findDOMNode()

組件并不是真實的 DOM 節(jié)點(diǎn),而是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu),叫做虛擬 DOM (virtual DOM)。只有當(dāng)它插入文檔以后,才會變成真實的 DOM 。根據(jù) React 的設(shè)計,所有的 DOM 變動,都先在虛擬 DOM 上發(fā)生,然后再將實際發(fā)生變動的部分,反映在真實 DOM上,這種算法叫做 DOM diff ,它可以極大提高網(wǎng)頁的性能表現(xiàn)。

但是,有時需要從組件獲取真實 DOM 的節(jié)點(diǎn),這時就要用到 React.findDOMNode 方法(查看 demo06 )。

var MyComponent = React.createClass({  handleClick: function() {    React.findDOMNode(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>    );  }});React.render(  <MyComponent />,  document.getElementById('example'));

上面代碼中,組件 MyComponent 的子節(jié)點(diǎn)有一個文本輸入框,用于獲取用戶的輸入。這時就必須獲取真實的 DOM 節(jié)點(diǎn),虛擬 DOM 是拿不到用戶輸入的。為了做到這一點(diǎn),文本輸入框必須有一個 ref 屬性,然后 this.refs.[refName] 就指向這個虛擬 DOM 的子節(jié)點(diǎn),最后通過 React.findDOMNode 方法獲取真實 DOM 的節(jié)點(diǎn)。

需要注意的是,由于 React.findDOMNode 方法獲取的是真實 DOM ,所以必須等到虛擬 DOM 插入文檔以后,才能使用這個方法,否則會返回 null 。上面代碼中,通過為組件指定 Click 事件的回調(diào)函數(shù),確保了只有等到真實 DOM 發(fā)生 Click 事件之后,才會調(diào)用 React.findDOMNode 方法。

React 組件支持很多事件,除了 Click 事件以外,還有 KeyDown 、Copy、Scroll 等,完整的事件清單請查看官方文檔。

七、this.state

組件免不了要與用戶互動,React 的一大創(chuàng)新,就是將組件看成是一個狀態(tài)機(jī),一開始有一個初始狀態(tài),然后用戶互動,導(dǎo)致狀態(tài)變化,從而觸發(fā)重新渲染 UI (查看 demo07 )。

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>    );  }});React.render(  <LikeButton />,  document.getElementById('example'));

上面代碼是一個 LikeButton 組件,它的 getInitialState 方法用于定義初始狀態(tài),也就是一個對象,這個對象可以通過 this.state 屬性讀取。當(dāng)用戶點(diǎn)擊組件,導(dǎo)致狀態(tài)變化,this.setState 方法就修改狀態(tài)值,每次修改以后,自動調(diào)用 this.render 方法,再次渲染組件。

由于 this.props 和 this.state 都用于描述組件的特性,可能會產(chǎn)生混淆。一個簡單的區(qū)分方法是,this.props 表示那些一旦定義,就不再改變的特性,而 this.state 是會隨著用戶互動而產(chǎn)生變化的特性。

八、表單

用戶在表單填入的內(nèi)容,屬于用戶跟組件的互動,所以不能用 this.props 讀?。ú榭?demo08 )。

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>    );  }});React.render(<Input/>, document.body);

上面代碼中,文本輸入框的值,不能用 this.props.value 讀取,而要定義一個 onChange 事件的回調(diào)函數(shù),通過 event.target.value 讀取用戶輸入的值。textarea 元素、select元素、radio元素都屬于這種情況,更多介紹請參考官方文檔。

九、組件的生命周期

組件的生命周期分成三個狀態(tài):

  • Mounting:已插入真實 DOM
  • Updating:正在被重新渲染
  • Unmounting:已移出真實 DOM

React 為每個狀態(tài)都提供了兩種處理函數(shù),will 函數(shù)在進(jìn)入狀態(tài)之前調(diào)用,did 函數(shù)在進(jìn)入狀態(tài)之后調(diào)用,三種狀態(tài)共計五種處理函數(shù)。

  • componentWillMount()
  • componentDidMount()
  • componentWillUpdate(object nextProps, object nextState)
  • componentDidUpdate(object prevProps, object prevState)
  • componentWillUnmount()

此外,React 還提供兩種特殊狀態(tài)的處理函數(shù)。

  • componentWillReceiveProps(object nextProps):已加載組件收到新的參數(shù)時調(diào)用
  • shouldComponentUpdate(object nextProps, object nextState):組件判斷是否重新渲染時調(diào)用

這些方法的詳細(xì)說明,可以參考官方文檔。下面是一個例子(查看 demo09 )。

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>    );  }});React.render(  <Hello name="world"/>,  document.body);

上面代碼在hello組件加載以后,通過 componentDidMount 方法設(shè)置一個定時器,每隔100毫秒,就重新設(shè)置組件的透明度,從而引發(fā)重新渲染。

另外,組件的style屬性的設(shè)置方式也值得注意,不能寫成

style="opacity:{this.state.opacity};"

而要寫成

style={{opacity: this.state.opacity}}

這是因為 React 組件樣式是一個對象,所以第一重大括號表示這是 JavaScript 語法,第二重大括號表示樣式對象。

十、Ajax

組件的數(shù)據(jù)來源,通常是通過 Ajax 請求從服務(wù)器獲取,可以使用 componentDidMount 方法設(shè)置 Ajax 請求,等到請求成功,再用 this.setState 方法重新渲染 UI (查看 demo10 )。

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>    );  }});React.render(  <UserGist source="

上面代碼使用 jQuery 完成 Ajax 請求,這是為了便于說明。React 沒有任何依賴,完全可以使用其他庫。

十一、參考鏈接

  1. React's official site
  2. React's official examples
  3. React (Virtual) DOM Terminology, by Sebastian Markb?ge
  4. The React Quick Start Guide, by Jack Callister
  5. Learning React.js: Getting Started and Concepts, by Ken Wheeler
  6. Getting started with React, by Ryan Clark
  7. React JS Tutorial and Guide to the Gotchas, by Justin Deal
  8. React Primer, by Binary Muse
  9. jQuery versus React.js thinking, by zigomir

(完)

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服