目錄: 一、前言 二、什麼是React 三、開發環境搭建 四、預備知識 五、最簡單的React小程式 六、基礎語法介紹 七、總結 八、參考資料 目錄: 一、前言 二、什麼是React 三、開發環境搭建 四、預備知識 五、最簡單的React小程式 六、基礎語法介紹 七、總結 八、參考資料 一、前言 近 ...
目錄: 一、前言 二、什麼是React 三、開發環境搭建 四、預備知識 五、最簡單的React小程式 六、基礎語法介紹 七、總結 八、參考資料 一、前言 近段時間看到學長公司招聘React Native工程師,當時比較好奇,就搜索了一下,然後剛好需要每個月買一本書看看,所以就買了一本《Reactive Native 開髮指南》。 但是看到裡面的預備知識的時候,發現首先最好需要先瞭解一下React(書中寫道:我們假設你對React已經有了一些瞭解),心想是不是還要買一本React的書籍,後來想想乾脆直接從網上搜搜教程吧,因此開始去探索,最終找到了三個鏈接的內容講的React還不錯,一個是阮一峰的博客,一個是官方文檔,一個是React概覽。阮一峰的博客和React概覽都是中文的,而且寫的比較容易理解,而官方文檔是英文的,講解的都比較詳細。所以如果自己英文好的話可以直接看官方文檔。 二、什麼是React React是一個JavaScript庫,是由FaceBook和Instagram開發的,主要用於用戶創建圖形化界面。 三、開發環境的搭建 做任何開發環境,我都會想著首先需要搭建一個環境來開發。就像如果開發iOS,你需要有蘋果電腦,然後從AppStore下載Xcode,然後就可以熟悉一個Xcode,看看文檔,就可以開始開發了;就像如果開發Android,你需要安裝Android Studio,然後需要安裝Java環境,然後就可以進行開發了。對於React,經過瞭解,我發現任何一個工具,比如Sublime Text,IntelliJ IDEA等等都可以,你甚至直接可以使用文本編輯器等等。這裡面我使用的是IntelliJ IDEA。 1、安裝一個IntellJ IDEA就可以進行開發了。 2、一個瀏覽器(這裡面我使用的是Chrome) 3、下載相關庫(下載鏈接) 四、預備知識 這個博客主要是介紹的React,我也假設一下:你需要對HTML,CSS,JavaScript有一定的瞭解,因為代碼大部分都是用這些來進行開發的。 五、最簡單的React小程式 我學任何語言的時候第一個程式都是一個Hello,World!。現在就讓我們來利用React來寫一個最簡單的Hello,World! 直接上代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello world!</title> <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"> ReactDOM.render( <h1>Hello,World!</h1>, document.getElementById('example') ); </script> </body> </html>然後用瀏覽器打開就可以了(這裡假設你已經會使用IntellJ IDEA,如果不會就先使用Sublime Text),然後在瀏覽器裡面就可以看到你特別熟悉的Hello,World!了。 簡單分析一下這個程式,首先,head裡面引入了三個js文件。前兩個是react的js文件,你可以在目錄三裡面的下載相關庫裡面拿。還有一個是browser.min.js,為什麼要引入這個js可以參考這個提問,其實是為了將JSX語法轉換成JavaScript語法。可以百度谷歌一下,下載該文件,也可以直接引用網上資源。然後就在html裡面寫了一個script代碼塊:
<script type="text/babel"> ReactDOM.render( <h1>Hello,World!</h1>, document.getElementById('example') ); </script>這裡需要註意:首先,/h1>後面是此外,以前我們可能使用的是type是text/javascript,現在我們使用的text/babel。這是因為React獨有的JSX語法,跟JavaScript不相容,凡是使用JSX的地方,都要加上type = “text/babel”。 是不是已經開放蒙圈了,剛纔提了好幾個JSX,什麼是JSX呢?React官方文檔裡面的解釋是:XML語法內部包含JavaScript被叫做JSX。但是我理解的應該是我們直接在JS裡面嵌入了HTML,這個就是React提出的叫做JSX的語法吧。這樣做的好處就是一個組件的開發過程中,HTML是必不可少的一部分,能夠將HTML封裝起來才是組件的完全體。JSX語法的產生,讓前端實現組件化成為了可能。 JSX的基本語法規則:遇到HTML標簽(以<開頭),就用HTML規則解析;遇到代碼塊(以{開頭),就用JavaScript規則解析。 在ReactDOM.render裡面寫了兩行,他們的作用就是將h1標題插入example節點。 你也可以直接新建一個js文件,然後將body里script裡面的代碼直接放到裡面,我們可以命名為helloworld.js,然後在head裡面導入即可。我比較傾向於這種做法,因為至少html文件不會看著太大,而且方便引入管理。如果其他html也需要改代碼塊,直接引入即可。 六、基礎語法介紹 1、ReactDOM.render( ) ReactDOM.render是React最基本的語法,用於將模板轉換成HTML語言,並插入指定的DOM節點。
ReactDOM.render( <h1>Hello,World!</h1>, document.getElementById('example') );運行結果如下: 2、map(遍歷) 將數組中的元素遍歷賦值
var animals = ['dog','cat','pig']; ReactDOM.render( <div> { animals.map(function(animal) { return <h1>{animal}</h1> }) } </div>, document.getElementById('example') );從這裡開始都是講React代碼放到了.js文件裡面,然後在html文件裡面引入。引入的時候記得寫type = ’text/babel’。這裡會有一個小問題:打開瀏覽器的調試工具後,裡面會看到Warning如下:
Warning: Each child in an array or iterator should have a unique "key" prop. Check the top-level render call using <div>解決方法如下:
var animals = ['dog','cat','pig']; ReactDOM.render( <div> { animals.map(function(animal,key) { return <h1 key = {key}>{animal}</h1> }) } </div>, document.getElementById('example') );警告的意思是最好給迴圈產生的child添加一個key。這樣就可以接觸警告了。運行結果如下: 這裡面你也許還會遇到另外一個問題,那就是用的Sublime Text,然後太瀏覽器打開的時候提示:
browser.min.js:3 XMLHttpRequest cannot load file:///Users/**/***/React/MyReactDemo/helloworld/src/helloworld.js.其實是因為我們將js單獨拉出來文件導致的,但是你會發現如果使用Safari瀏覽器是沒有這個問題的。在這裡找到了答案:
Cross origin requests are only supported for protocol schemes:
http, data, chrome, chrome-extension, https, chrome-extension-resource.
startup chrome with --disable-web-security
On Windows:
chrome.exe --disable-web-security
On Mac:
open /Applications/Google\ Chrome.app/ --args --disable-web-security
因為Chrome瀏覽器不支持本地ajax訪問。
你也可以構建本地伺服器進行訪問,比如我使用的intellJ IDEA ,直接就是在本地構建了一個本地服務,此時訪問地址為:
http://localhost:63342/MyReactDemo/helloworld/src/helloworld.html而沒有構建本地服務的時候訪問地址為:
file:///Users/zhanggui/zhanggui/React/MyReactDemo/helloworld/src/helloworld.html
3、組件化
因為React使用的是JSX,所以它允許將代碼封裝成組件(component),然後像普通的HTML標簽一樣插入。React.createClass方法就是用於生成一個組件類,比如: var ZGButton = React.createClass({ render:function() { return <button>ZG{this.props.name}</button> } }); ReactDOM.render( <ZGButton name = 'Button1'/>, document.getElementById('example') );運行結果如下: 上面的ZGButton就是一個組件類,模板插入<ZGButton />,會自動生成一個該組件的實例。 所有組件類都必須有自己的render方法,用於輸出組件。 現在代碼這樣寫:
var zGButton = React.createClass({ render:function() { return <button>ZG{this.props.name}</button> } }); ReactDOM.render( <zGButton name="Button2">Button</zGButton>, document.getElementById('example') );也就是將組件類的第一個字元小寫,然後在引用的時候發現現在是雙標簽了(代碼自動填充的時候出現),而且name失效。因此我們在開發組件的時候一定要將第一個首字元大寫,否則將不會達到你想要的效果。 4、this.props.children this.props對象的屬性和組件的屬性一一對應,但是有個children除外,它表示的是組件的所有子節點:
var Students = React.createClass({ render:function() { return ( <ol> { React.Children.map(this.props.children,function(child) { return <li>{child}</li> }) } </ol> ); } }); ReactDOM.render( <Students> <span>zhangsan</span> <span>lisi</span> </Students>, document.getElementById('example') );此時輸出的結果為: 5、PropTypes 組件就類似與我們OC開發或者Java開發中的類,類可以進行屬性添加,組件也可以。 組件的屬性可以接受任意值,字元串、對象、函數都行。這裡面有一個propTypes,可以用來限定提供的屬性是否滿足要求:
var Student = React.createClass({ propTypes: { myName:React.PropTypes.string.isRequired, }, render:function() { return <h1> {this.props.myName} </h1> } }); var myNameStr = "React"; ReactDOM.render( <Student myName = {myNameStr} />, document.getElementById('example') );這裡面的propTypes裡面的是對屬性的限制,比如這裡必須是string類型,值是必須的。我們還可以去設置預設屬性值:
var Student = React.createClass({ getDefaultProps: function() { return { myName:"Default React" } }, propTypes: { myName:React.PropTypes.string.isRequired, }, render:function() { return <h1> {this.props.myName} </h1> } });這裡面的getDefaultProps就類似與我們在開發iOS或者Java的時候對聲明屬性的時候進行賦初始化值。 6、Virtual DOM 組件並不是真實的DOM節點,而是存在於記憶體中的一種數據結構,叫做虛擬DOM,只有插入文檔的時候才會變成真實的DOM。根據React的設計,當重新渲染組件的時候,會通多diff尋找到變更的DOM節點,再把這個修改更新到瀏覽器實際的DOM節點上,所以實際上並不是渲染整個DOM數,這個Virtual DOM是一個純粹的JS數據結構,性能比原生DOM快很多。這裡面我們可以用通過ref屬性來獲取真實的DOM屬性:
var MyComponment = React.createClass({ render:function(){ return ( <div> <input type = "text" ref = "myTextInput"/> <input type = "button" value = "Focus the text input" onClick={this.handleClick}/> </div> ); }, handleClick:function() { // alert(this.refs.myTextInput); this.refs.myTextInput.focus(); } }); ReactDOM.render( <MyComponment/>, document.getElementById('example') );這裡需要註意的是,因為我們使用的是真實的DOM對象,所以一定要確保DOM插入文檔之後才能夠使用。 7、this.state 我們可以通過this.state來拿到組件的狀態:
var LinkButton = React.createClass({ getInitialState:function () { return {linked:false}; }, handleClick:function() { this.setState({linked:!this.state.linked}); }, render:function() { var text = this.state.linked? 'linked':'not linked'; return ( <p onClick={this.handleClick}> You {text} this. Click to toggle </p> ); } }); ReactDOM.render( <LinkButton/>, document.getElementById('example') );這裡面我設置了一個linked的狀態(是否連接),這裡通過this.state拿到當前狀態,通過this.setState來設置狀態。 8、表單 表單填寫是用戶和組件的互動:
var Form = 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( <Form/>, document.getElementById('example') );9、Component Lifecycle 組件有三個主要的生命周期: Mounting:組件插入到DOM Updating:組件被重新渲染,如果DOM需要更新 Unmounting:從DOM中刪除組件 React為每個狀態都提供了兩種處理函數,will函數在進入狀態之前調用,did在進入狀態之後調用。詳情可參見這裡。
var MyButton = React.createClass({ componentDidMount:function() { alert("已經裝載"); }, componentWillMount:function() { alert("將要裝載"); }, componentWillUpdate:function() { alert("將要更新"); }, componentDidUpdate:function() { alert("已經更新"); }, componentWillUnmount:function() { alert("將要移除"); }, render:function(){ return ( <button>MyButton</button> ); }, }); var LoadButton = React.createClass({ loadMyButton:function() { ReactDOM.render( <MyButton/>, document.getElementById('myBTN') ); }, removeMyButton:function() { var result = ReactDOM.unmountComponentAtNode(document.getElementById('myBTN')); console.log(result); }, render:function() { return ( <div> <button onClick={this.removeMyButton}>卸載MyButton</button> <button onClick={this.loadMyButton}>裝載MyButton</button> <div id="myBTN">這裡是mybuttonquyu</div> </div> ); } }); ReactDOM.render( <LoadButton/>, document.getElementById('example') );10、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.getElementById('example') );這裡使用了$,所以要引入jquery.js。 七、總結 經過這兩天的瞭解,大概對React入門了。個人覺得React就是為了組件化開發方便而產生的。利用React,可以讓其充當MVC中V的角色。也是對MVC架構的輔助設計。 八、參考資料 1、阮一峰的博客 2、React官方文檔 3、React入門教程