JSX即JavaScript XML,一種在React組件內部構建標籤的類XML語法。
在不使用JSX的狀況下,React程序中建立DOM是這樣的:html
//v0.11 React.DOM.h1({className: 'title'}, 'Title'); //v0.12 React.createElement('h1', {className: 'title'}, 'Title');
若是使用JSX的方式建立節點爲:node
<h1 className="title">Title</h1>
JSX的特徵:react
JSX是一種句法變換,每個JSX節點都對應着一個JavaScript函數jquery
JSX即不提供也不須要運行時庫git
JSX並無改變或者添加JavaScript的語義,它只是簡單的函數調用。github
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> ReactDOM.render( <h1>Hello,react!</h1>, document.getElementById('example') ); </script> </body> </html>
要點一:在整個Html文件中,只有定義了一個id爲example的div標籤,當程序運行時,JavaScript代碼執行,
React會建立新的DOM節點,也就是<h1>Hello,react!</h1>。
ReactDOM.render(newDom,parentDom);這個函數是用來對視圖進行渲染新的節點,函數的參數主要有兩個,
一個是新的節點,另外一個是新節點要放在哪一個父節點中。ajax
要點二:<script> 標籤的 type 屬性爲 "text/babel" 。這是由於 React 獨有的 JSX 語法,跟
JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel"算法
要點三:ReactDOM.render()方法中的第一個參數,也就是新的節點,只能有一個頂層的標籤,而後裏面嵌套多個子節點,
例以下面的寫法就是不可行的:json
//Error ReactDOM.render( <p>Error</P> <h1>Hello,react!</h1>, document.getElementById('example') );
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> var names = ['lgy','Kb']; ReactDOM.render( <div> { names.map((name) => { return <div>Hello,{name} !</div> }) } </div>, document.getElementById('example') ); </script> </body> </html>
要點:經過在JavaScript中定義變量,可嵌入JSX中使用動態變量,使用的語法爲:<div>Hello,{name} !</div>api
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> var arr = [ <h1>Hello react</h1>, <h2>Hello Node</h2> ]; ReactDOM.render( <div>{arr}</div>, document.getElementById('example') ); </script> </body> </html>
要點:能夠經過傳入節點數組的方式,直接把數組給予新的節點,<div>{arr}</div>,JSX語法會根據數組的元素動態生成對應的子節點
React的組件化模式是最大的亮點,組件中使用props或者state,當這兩個變量改變時,相應的DOM表現也會有所改變,這主要緣由是一個
組件是一個狀態機,對於特定的輸入,他總會返回一致的輸出。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> console.log(React); class HelloMessage extends React.Component{ render() { return <h1>Hello {this.props.name}</h1>; } } ReactDOM.render( <HelloMessage name="LGY" />, document.getElementById('example') ); </script> </body> </html>
要點一: 構造一個組件的語法使用ES6的標準進行,經過繼承React.Component,使用render() {...}進行渲染對應的標籤和變量輸出組件
要點二: 命名新構造的組件的第一個字母須要大寫!!!
要點三: 使用構造好的組件,經過使用標籤<HelloMessage name="LGY"/>,其中name是傳遞進去的參數,在內部用this.props.name進行
調用變量
1.Mounting:已插入真實 DOM
2.Updating:正在被從新渲染
3.Unmounting:已移出真實 DOM
1.componentWillMount():改方法在完成首次渲染以前被調用。是在render方法調用前能夠修改組件state的最後一次機會
2.componentDidMount():當render方法成功調用後,且DOM已經被渲染,能夠在componentDidMount內部經過this.getDOMNode()方法訪問到DOM節點
3.componentWillUpdate(object nextProps, object nextState):組件在收到新的props或者state進行渲染以前,這時調用該方法
4.componentDidUpdate(object prevProps, object prevState):這個方法可讓咱們更新已經渲染好的DOM的機會
5.componentWillUnmount():當組件的生命結束時,這個方法就會被調用
1.componentWillReceiveProps(object nextProps):已加載組件收到新的參數時調用
2.shouldComponentUpdate(object nextProps, object nextState):組件判斷是否從新渲染時調用
經過props能夠把任意類型的數據傳遞給組件
var tables = [{title: 'React'}] <TableList tables={tables} />
能夠經過this.props.tables訪問對應的屬性,然絕對不能修改。一個組件絕對不能夠本身修改本身的props!!!
經過在組件中定義一個配置對象。組件初始化時,若是傳遞的屬性和propsTypes不匹配,就會打印一個console.warn日誌,
若是是可選的配置,就能夠去掉isRequired。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> class MyTitle extends React.Component{ render() { return <h1>{this.props.title}</h1>; } } MyTitle.propTypes = { title: React.PropTypes.string.isRequired } //設置默認屬性 MyTitle.defaultProps = { title: "lgy" } var data = 'KB'; ReactDOM.render( <MyTitle title={data}/>, document.getElementById('example') ); </script> </body> </html>
要點: 示例中定義了一個組件MyTitle,其中使用propTyps對組件的屬性類型進行匹配,defaultProps對組件的屬性類型設置默認值。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> class NodeList extends React.Component{ render() { return ( <ol> { React.Children.map(this.props.children,(child) => { return <li>{child}</li>; }) } </ol> ); } } ReactDOM.render( <NodeList> <span>Hello!</span> <p>LGY</p> </NodeList>, document.getElementById('example') ); </script> </body> </html>
要點: 經過this.props.children來獲取組件的子節點
每一個React組件均可以擁有本身的state,state與props的區別在於前者只存在於組件的內部中,this.props
表示那些一旦定義,就再也不改變的特性,而 this.state 是會隨着用戶互動而產生變化的特性。state能夠肯定
視圖的狀態。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> class LikeButton extends React.Component { constructor(props) { super(props); console.log(this); this.state = {liked: false}; } handleClick(event) { console.log(this); this.setState({liked: !this.state.liked}); }; render() { var text = this.state.liked ? 'like' : 'haven\' t liked'; return( <div> <input type="button" value="Click to toggle." onClick={this.handleClick.bind(this)} /> <p>You {text} this.</p> </div> ); } } ReactDOM.render( <LikeButton />, document.getElementById('example') ); </script> </body> </html>
要點:組件LikeButton經過constructor構造函數進行初始化狀態,this.state = {liked: false} 把liked的狀態設置爲false,
而後經過handleClick綁定this,當用戶點擊按鈕時,改變liked變量的狀態,這時視圖也會隨着一塊兒改變。
組件並非真實的 DOM 節點,而是存在於內存之中的一種數據結構,叫作虛擬 DOM (virtual DOM)。只有當它
插入文檔之後,纔會變成真實的 DOM 。根據 React 的設計,全部的 DOM 變更,都先在虛擬 DOM 上發生,而後
再將實際發生變更的部分,反映在真實 DOM上,這種算法叫作 DOM diff ,它能夠極大提升網頁的性能表現。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> var MyComponent = React.createClass({ handleClick: function() { if (this.myTextInput !== null) { this.refs.myText.focus(); } }, render: function() { return ( <div> <input type="text" ref="myText" /> <input type="button" value="Focus the text input" onClick={this.handleClick} /> </div> ); } }); ReactDOM.render( <MyComponent />, document.getElementById('example') ); </script> </body> </html>
要點:組件 MyComponent 的子節點有一個文本輸入框,用於獲取用戶的輸入。這時就必須獲取真實的 DOM 節點,虛擬 DOM 是拿不到用戶
輸入的。爲了作到這一點,文本輸入框必須有一個 ref 屬性,而後 this.refs.[refName] 就會返回這個真實的 DOM 節點。須要注意的
是,因爲 this.refs.[refName] 屬性獲取的是真實 DOM ,因此必須等到虛擬 DOM 插入文檔之後,才能使用這個屬性,不然會報錯。上
面代碼中,經過爲組件指定 Click 事件的回調函數,確保了只有等到真實 DOM 發生 Click 事件以後,纔會讀取 this.refs.[refName]
屬性。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> class Input extends React.Component { constructor(props) { super(props); this.state = {value:'Hello!'} } handleChange(event) { this.setState({value:event.target.value}); } render() { var value = this.state.value; return ( <div> <input type="text" value={value} onChange={this.handleChange.bind(this)}/> <p>{value}</p> </div> ); } } ReactDOM.render( <Input/>, document.getElementById("example") ); </script> </body> </html>
要點:文本輸入框的值,不能用 this.props.value 讀取,而要定義一個 onChange 事件的回調函數,經過
event.target.value 讀取用戶輸入的值。textarea 元素、select元素、radio元素都屬於這種狀況
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="../node_modules/jquery/dist/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> function get(source,callback) { var request = new Request(source); fetch(request) .then(res => res.json()) .then(arr => callback(arr[0])) } class UserGist extends React.Component { constructor(props) { super(props); this.state = {username: '',lastGistUrl: ''}; } componentDidMount() { var usr = get(this.props.source,(usr) => { this.setState({ username: usr.owner.login, lastGistUrl: usr.html_url }); }); } render() { var value = this.state.value; 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") ); </script> </body> </html>
要點:該實例代碼使用了Fetch API來進行數據獲取,Fetch API的具體如何使用在接下來的博客文章會介紹。
github倉庫連接:https://github.com/lgybetter/ReactDemo