寫 React 有兩種方式:css
經過 jsxhtml
經過 jsnode
jsx 寫起來感受會更方便,但就須要用babel進行編譯了。react
用babel編譯 React 的 jsx 有三種方法( 關於 babel 的具體使用方法好像仍是有不少疑問的。之後會再折騰下)git
CLI工具編譯github
Node.js運行時編譯ajax
瀏覽器(客戶端)運行時編譯npm
這樣我打算用 babel-cli 進行實時編譯,會比較方便。json
將工具全局安裝了:redux
$ [sudo] npm i -gd babel-cli
插件單獨安裝:
$ npm i -d babel-preset-react
ps:我這裏以前說錯了
這裏有個坑,在 windows 系統的話,能夠直接
babel --presets react
,但在 os x 會報錯,要直接直接指定絕對路徑/usr/local/lib/node_modules/babel-preset-react
,
babel-cli 的 --presets
參數是會向父級目錄尋找 node_module
裏面的 babel-prest-xxx
插件,若是沒有找到,就會相對於當前目錄路徑尋找插件。
除此以外,你也能夠寫成絕對路徑的插件地址。
在單獨安裝了插件後,你就能夠不用寫絕對路徑地址了。
$ babel --presets react jsx --watch --out-dir build
若是不想每次敲命令,能夠在項目目錄(就是敲babel命令的目錄)中新建一個.babelrc
文件:
{ "presets": ["react"] }
這樣敲命令的時候就能夠不要帶上--presets
參數了。
$ babel jsx --watch --out-dir build
jsx
是須要編譯的文件夾,build
是編譯後產出的文件夾。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="JBody"></div> <!-- react 核心 js--> <script src="http://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script> <!-- 編譯後的 jsx 引用 --> <script src="./build/test.js"></script> </body> </html>
ps:官網的示例中,react 核心 js 是放在 <head></head>
標籤裏面的,由於這樣的話,在最後渲染 DOM 的時候就能夠直接選擇在<body></body>
標籤裏面了。否則就要像我這樣,在<body></body>
標籤裏面給個節點供 react 進行渲染。
先來個 Input
組件。
var Input = React.createClass({ render: function(){ return( <label for={this.props.id}> <i>四月是誰的謊話</i> <input id={this.props.id} value type="text"/> </label> ) } })
經過 Reac.createClass
建立的就是組件了。rander
函數 return 的東西能夠稱做模板。
每一個組件都是一個樹形結構(有父級節點和子節點,也就是不能同時存在兩個頂級節點,react 是不容許的)。
在 React 裏面就是一個個組件組成的,組合在一塊兒就也是一個樹形結構。
ReactDOM.render( <Input />, document.getElementById('JBody') );
調用 ReactDOM.render
方法進行渲染,第一個參數是組件了,第二個是裝載該組件的容器。
一樣的,第一個參數只支持樹形結構,也就是隻有一個頂級節點。
props
就是一個組件模板的數據對象。裏面儲存着靜態的數據,也就是隻在調用時賦值,以後若是有數據的改變也不會再次進行模板的渲染了。
props 的使用:
var Input = React.createClass({ render: function(){ return( // 使用 props <label for={this.props.iid}> <i>四月是誰的謊話</i> <input id={this.props.iid} value type="text"/> </label> ) } }) ReactDOM.render( <Input iid="JWho"/>, // 賦值 props document.getElementById('JBody') )
state
跟 props
是相對的。state
是動態的數據對象,也就是能夠任什麼時候候進行賦值,以後若是有數據的改變會進行模板的再次渲染(這裏渲染的話就涉及到了 react 的 virtual DOM)了。
state 的使用:
這裏定義個列表組件Items
var Items = React.createClass({ getInitialState: function() { return { data: [12312,1231,45,51512312,2131] } }, render: function(){ return( <ul> {this.state.data.map((value,i) => { return <li>{value}</li> })} </ul> ) } })
getInitialState
用來定義 state
的初始數據。
還能夠在組件的生命週期函數裏能夠從服務器獲取數據而後經過調用 this.setState
方法進行對 state
賦值。
this.setState
就是那個 能夠任什麼時候候進行賦值
的方法了。
改造下 Input
組件,state
示例:
var Input = React.createClass({ getInitialState: function() { return { who: '我' } }, change: function(e){ let target = e.target this.setState({ who : target.value }) }, render: function(){ // 使用 props return( <div> <label for={this.props.iid}> <i>四月是誰的謊話?</i> <input id={this.props.iid} onChange={this.change} type="text"/> </label> <p>{`四月是${this.state.who}的謊話`}</p> </div> ) } }) ReactDOM.render( <Input />, document.getElementById('JBody') )
這裏進行了事件 onChange
的調用,當觸發 change 事件的時候,state
就會進行改版了。
關於時間系統的文檔:
react 的核心中是沒有關於兩個不一樣組件之間的相互通訊的方法的,可是官方給出了一種flux的通訊概念、flux中文文檔,然而社區彷佛並不以爲這一套方案很好用,因而有了另外一種通訊概念redux。
react 的組件化概念是很明確的,但對於組件之間通訊能夠說是基本沒有。
在個人理解裏面,組件的通訊能夠更明確地理解爲數據的通訊,由於數據和組件渲染分離是很重要的。
一個負責不一樣組件渲染的組件容器,會自行判斷數據的狀態從而進行最終組件的渲染。這樣就能作到數據和組件渲染的分離了。這個概念就是Container Components
、Leveling Up With React: Container Components
在其餘的一些mv*
框架裏面,每一個組件都有本身的通訊接口,從而能夠在A組件裏面跟B組件進行數據通訊,但 react 倒是沒有這樣的接口,從而咱們就須要一個藉助一些通訊工具,好比手機、電腦什麼的。
沒錯,咱們能夠把 Flux、Redux 這些工具當成通訊工具來看待,若是你喜歡,你徹底能夠用寫信的方式(本身寫一個觀察者模式的函數)。當A組件的數據要與B組件的數據進行打電話的時候,撥通B組件的電話號碼,而後把數據告訴B組件就能夠了。數據會在運營商的系統裏面走一遭,而後傳到B組件那裏的。
例如登陸。
在一個頁面上,若是存在兩個或兩個以上須要獲取登陸信息的組件,就將須要進行通訊了。
當一個組件進行了登陸以後,應該通知其餘須要更新登陸信息的組件。這樣就產生了通訊的需求了。
這塊到沒有太多的實踐,組件的拆分、定義是一門深思熟慮的藝術。等有實踐經驗找到門路以後再作補充。
但這塊多是不少人會忽略的,優秀的抽象封裝首先應該是針對方便開發和維護的,其次纔是複用。