您好,登錄后才能下訂單哦!
React 起源于 Facebook 的內部項目,因為該公司對市場上所有 JavaScript MVC 框架,都不滿意,就決定自己寫一套,用來架設 Instagram 的網站。做出來以后,發現這套東西很好用,就在2013年5月開源了。由于 React 的設計思想極其獨特,屬于革命性創新,性能出眾,代碼邏輯卻非常簡單。所以,越來越多的人開始關注和使用,認為它可能是將來 Web 開發的主流工具。
ReactJS官網地址:http://facebook.github.io/react/
Github地址:https://github.com/facebook/react
React認為一個組件應該具有如下特征:
(1)可組合(Composeable):一個組件易于和其它組件一起使用,或者嵌套在另一個組件內部。如果一個組件內部創建了另一個組件,那么說父組件擁有(own)它創建的子組件,通過這個特性,一個復雜的UI可以拆分成多個簡單的UI組件;
(2)可重用(Reusable):每個組件都是具有獨立功能的,它可以被使用在多個UI場景;
(3)可維護(Maintainable):每個小的組件僅僅包含自身的邏輯,更容易被理解和維護;
我們新建一個html文件,引用react.js和JSXTransformer.js這兩個js文件。html模板如下(js路徑改成自己的):
<!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>
script的type是text/babel,這是因為 React 獨有的 JSX 語法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel" 。
其次,上面代碼一共用了三個庫: react.js 、react-dom.js 和 Browser.js ,它們必須首先加載。其中,react.js 是 React 的核心庫,react-dom.js 是提供與 DOM 相關的功能,Browser.js 的作用是將 JSX 語法轉為 JavaScript 語法,這一步很消耗時間,實際上線的時候,應該將它放到服務器完成。
下面開始看react該怎么寫,還是傳統的老規矩 hello word:
<!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"> ReactDOM.render(<h2>hello word</h2>,document.getElementById('example')); </script> </body> </html>
在上例的body中,有一個div,id是example, 然后由react的渲染器把h2標簽渲染到該div中。
ReactDOM.render(DOM節點,被插入的父節點);
這一句代碼是最常用也是非常必要的一句。 這句中有個很重要的地方就是html語法和js語法的混寫,這是jsx語法的特點,在jsx語法里,遇到 尖括號就按照html來解析,遇到花括號就按照js語法去解析。下面這個例子更能說明jsx語法的寫法:
var list = ["word","man","boy"]; ReactDOM.render( <div> { list.map(function (name){ return <div> hello {name}</div> }) } </div>,document.getElementById('example')); </script>
最終的結果是:
hello word
hello man
hello boy
這里有一點需要說明的是 ReactDOM.render 渲染器的第一個參數里,有且只能有一個頂級節點,不能有多個并列,否則會報錯。JSX 允許直接在模板插入 JavaScript 變量。如果這個變量是一個數組,則會展開這個數組的所有成員。
var list = [<h2>word</h2>,<h2>man</h2>,<h2>boy</h2>]; ReactDOM.render(<div>{list}</div>,document.getElementById('example')); </script>
最終結果是:
React 允許將代碼封裝成組件(component),然后像插入普通 HTML 標簽一樣,在網頁中插入這個組件。React.createClass 方法就用于生成一個組件類:
var HelloWord = React.createClass({ render:function(){ return <p>hello {this.props.name}</p> } }); ReactDOM.render(<HelloWord name="喵星人"/>,document.getElementById('example'));
最終結果是:
hello 喵星人
上例中用React.createClass創建了一個組件類HelloWord,這里有一點需要注意:組件類名字的首字母必須是大寫的,否則會報錯。React.createClass接收一個對象,對象中必須有render屬性,render屬性的值一般都是寫成一個函數,然后返回一個DOM對象,別忘了上面說的,這個DOM對象有且只能有一個頂級節點,否則會報錯。
我們在上面的代碼的return 里會看到有這么一段:this.props.name,然后在ReactDom.render中的第一個參數里會看到標簽有一個屬性name="喵星人",這里需要記住的一點是name="喵星人"看上去就像在對函數傳參數,而this.props.name就是對參數的接收。
添加組件屬性,有一個地方需要注意,就是 class 屬性需要寫成 className ,for 屬性需要寫成 htmlFor ,這是因為 class 和 for 是 JavaScript 的保留字。
this.props 對象的屬性與組件的屬性一一對應,但是有一個例外,就是 this.props.children 屬性。它表示組件的所有子節點。
var NotesList = React.createClass({ render: function() { return ( <ol> { this.props.children.map(function (child) { return <li>{child}</li>; }) } </ol> ); }});ReactDOM.render( <NotesList> <span>hello</span> <span>world</span> <p>main</p> </NotesList>, document.getElementById('example'));
最終運行結果:
hello
world
3. main
2 和3之間的換行是因為p標簽會自帶一個換行,li標簽也會有一個換行,所以中間就有了一個空白行.
組件免不了要與用戶互動,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'));
最終結果:
You haven't liked this. Click to toggle.
當在文字上點擊時會變成:
You like this. Click to toggle.
然后一直點擊就會在兩句英文之間來回切換。
這里需要注意的是 getInitialState 是React默認的屬性,需要返回一個對象,可以是NULL或者其他,表示初始狀態,返回的對象中可以不止有一個屬性,修改這些狀態可以使用react提供的方法this.setState(對象), 這里的對象可以只修改初始狀態中的某一個屬性,也可以同時修改多個。當任何一個狀態改變的時候react就會重新調用 render屬性所指向的函數,也就意味著會重新渲染該組件。
組件的生命周期分成三個狀態:
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毫秒,就重新設置組件的透明度,從而引發重新渲染。這里需要注意的地方是在setInterval的第一個參數也就是計時器觸發函數后使用了bind(this),計時器函數中不能直接使用this來獲取react的狀態或屬性,需要綁定this。
小結:
react提供的屬性:
getInitialState 設置默認狀態
setState 修改狀態
render 返回組件
componentWillMount() 插入真實DOM之前調用
componentDidMount() 插入真實DOM之后調用
componentWillUpdate(object nextProps, object nextState) 重新渲染之前調用
componentDidUpdate(object prevProps, object prevState) 重新渲染之后調用
componentWillUnmount() 移出真實DOM之前調用
propTypes 驗證組件實例的屬性是否符合要求
getDefaultProps 設置組件屬性的默認值。
最后兩個屬性本文中沒有介紹,詳細介紹請參閱http://www.ruanyifeng.com/blog/2015/03/react.html
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。