什么是React
以下是官方定義,反正我是沒看懂。google了下,大家都稱之“前端UI開發框架”,勉強這么叫著吧。可以看下這篇文章對react的介紹,本文更多的是覆蓋react的入門實踐。
A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES
本文提到的例子可以在這里找到:github鏈接
getting started
getting-started.html
里的例子比較簡單,首先引入 react.js
、JSXTransformer.js
,然后通過 React.render()
方法即可。語法細節什么的可以先不管。
需要注意的點是,最后一段script標簽,上面聲明了 type="text/jsx"
,也就是說并不是通常的直接解析執行的腳本,JSXTransformer.js
會對其進行預編譯后再執行。
<!DOCTYPE html> <html> <head> <title>getting started</title> <script src="build/react.js"></script> <script src="build/JSXTransformer.js"></script> </head> <body> <div id="example"></div> <script type="text/jsx"> React.render( <h1>Hello, world!</h1>, document.getElementById('example') ); </script> </body> </html>
好了,看下效果吧。
文件分離
根據以往養成的好習慣,直覺的感覺到,這里應該將組件的定義跟 html 頁面分離,不然以后頁面肯定就亂糟糟了。示例請查看 separate-file.html
修改后的html文件,瞬間清爽很多。同樣需要注意 type="text/jsx"
<!DOCTYPE html> <html> <head> <title>demo</title> <script src="build/react.js"></script> <script src="build/JSXTransformer.js"></script> </head> <body> <div id="example"></div> <script type="text/jsx" src="js/helloworld.js"></script> </body> </html>
處理后的 helloworld.js
,其實內容一點變化都沒有
React.render( <h1>Hello, world!</h1>, document.getElementById('example') );
好了,查看效果。雙擊 separate-file.html
,這時看到頁面是空白的,同時控制臺還有錯誤信息。
腫么辦呢?相信有經驗的兄弟知道咋整了。這里偷個懶,直接用fis
起個本地服務器。在2015.04.09-react/
根路徑下運行
Server端編譯
之前提到,JSXTransformer.js
會對標志 type="text/jsx"
的script 進行預編譯后再執行,那么在瀏覽器端很可能就會遇到性能問題(沒驗證過)。React 的開發團隊當然也考慮到這個問題了,于是也提供了server端的編譯工具。
請查看 server-build-without-transform.html
。這里我們已經把 JSXTransformer.js
的依賴去掉。相對應的,我們需要在server端做一定的編譯工作。
<!DOCTYPE html> <html> <head> <title>demo</title> <script src="build/react.js"></script> <!-- <script src="build/JSXTransformer.js"></script> --> </head> <body> <div id="example"></div> <script src="js-build/helloworld.js"></script> </body> </html>
挺簡單的,安裝 react-tools
,然后運行相應命令即可
npm install -g react-tools
jsx --watch js/ js-build/
可以看到,js/helloworld.js
已經被編譯成 js-build/helloworld.js
。我們看下編譯后的文件
編譯后的文件。可以看到,都是瀏覽器可以理解的語法。你也可以一開始就這樣編寫,不過保證你會抓狂。
React.render( React.createElement("h1", null, "Hello, world!"), document.getElementById('example') );
定義一個組件
下面定義一個極簡的組件 來做說明,示例代碼可以查看 define-a-component.html
。從代碼可以看到:
- 通過
React.createClass()
來定義一個組件,該方法需要定義render
方法來返回組件對應的 dom 結構 - 通過
React.render()
來調用組件。該方法傳入兩個參數,分別是 對應的組件,父級節點。
<!DOCTYPE html> <html> <head> <title>getting started</title> <script src="build/react.js"></script> <script src="build/JSXTransformer.js"></script> </head> <body> <div id="example"></div> <script type="text/jsx"> var HelloComponent = React.createClass({ render: function(){ return ( <div> <h1>Hello World</h1> <p>I am Hello World Component</p> </div> ); } }); React.render( <HelloComponent />, document.getElementById('example') ); </script> </body> </html>
示例效果如下:
剛接觸React組件定義的同學,可能會踩中下面的坑。比如把前面的組件定義改成。區別在于去掉了組件最外層的包裹節點 <div>
var HelloComponent = React.createClass({ render: function(){ return ( <h1>Hello World</h1> <p>I am Hello World Component</p> ); } });
再次訪問 http://127.0.0.1:8080/define-a-component.html 會有如下錯誤提示。錯誤信息比較明確了,不再贅述,乖乖加上包裹節點就好了
使用property
在定義一個組件時,我們通常會暴露一定的配置項,提高組件的可復用性。這里簡單示范下如何實現,具體代碼可查看 using-properties.html
。
關鍵代碼如下,還是比較直觀的。使用組件時,就跟使用瀏覽器內置的組件那樣給屬性賦值。在組件定義的內部代碼實現中,通過 this.props.xx
來取到對應的值即可。
<script type="text/jsx"> var HelloComponent = React.createClass({ render: function(){ return ( <div> <h1>Title is: {this.props.title}</h1> <p>Content is: {this.props.content}</p> </div> ); } }); React.render( <HelloComponent title="hello" content="world" />, document.getElementById('example') ); </script>
組件嵌套
推薦看下 Thinking in React 這篇文章。要實現文中提到的 搭積木式的開發模式,組件的嵌套使用是必不可少的。下面示范下,具體代碼查看 compose-components.html
。
<!DOCTYPE html> <html> <head> <title>demo</title> <script src="build/react.js"></script> <script src="build/JSXTransformer.js"></script> </head> <body> <div id="example"></div> <script type="text/jsx"> var Title = React.createClass({ render: function(){ return ( <h1>This is Title</h1> ); } }); var Content = React.createClass({ render: function(){ return ( <p>This is Content</p> ); } }); // Article組件包含了 Title、Content 組件 var Article = React.createClass({ render: function() { return ( <div class="article"> <Title /> <Content /> </div> ); } }); React.render( <Article />, document.getElementById('example') ); </script> </body> </html>
組件更新
在React的體系中,組件的UI會隨著組件狀態的變化(state)進行更新。從圍觀的代碼層面來說,是 setState()
方法被調用時,組件的UI會刷新。簡單例子可以參考 update-if-state-chagne.html
。例子可能不是很恰當,就表達那么個意思。
其中有兩個方法簡單介紹下:
getInitialState
:返回組件的初始狀態。componentDidMount
:當組件渲染完成后調用的方法。
ps:React的組件更新機制是最大的亮點之一。看似全量刷新,實際內部是基于Virtual DOM機制的局部刷新,開發者無需再編寫大量的重復代碼來更新局部的dom節點。
Virtual DOM以及局部刷新實現機制,這里就不展開了,可參考 http://calendar.perfplanet.com/2013/diff/
<!DOCTYPE html> <html> <head> <title>demo</title> <script src="build/react.js"></script> <script src="build/JSXTransformer.js"></script> </head> <body> <div id="example"></div> <script type="text/jsx"> var HelloComponent = React.createClass({ getInitialState: function(){ return { title: 'title1', content: 'content1' }; }, componentDidMount: function(){ var that = this; setTimeout(function(){ that.setState({ title:'title2', content:'content2' }); }, 2000); }, render: function(){ return ( <div> <h1>Title is: {this.state.title}</h1> <p>Content is: {this.state.content}</p> </div> ); } }); React.render( <HelloComponent />, document.getElementById('example') ); </script> </body> </html>
訪問 http://127.0.0.1:8080/update-if-state-chage.html ,剛打開時,展示如下
2000ms后,界面刷新。
Virtual DOM
已經有人寫過了,這里直接附上參考鏈接:http://calendar.perfplanet.com/2013/diff/
react native
TODO 待填坑
文章列表