React是一個構建用戶界面的JavaScript庫,是Facebook公司在2013年5月在github上開源的。其特色以下:javascript
React的基本結構大體以下:html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@latest/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">java
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);react
</script>
</body>
</html>webpack
在這個React的基本結構裏,咱們須要明白三點:git
另外這個例子獲得的結果是顯示 Hello world! 而ReactDOM.render()就是一個核心方法。React代表這是由React提供的方法,DOM代表此方法與DOM密切相關,render的由於是「渲染」。因此這裏的意思就是將<h1>Hello,world!</h1>渲染到html中id爲example下。值得注意的是,在JavaScript中對於html標籤必定要打引號的,而這裏沒有使用引號,這也正體現了JSX的特別之處。可是JSX到底是什麼呢?它還有什麼特別的用處呢?下面咱們就能夠對它瞭解。程序員
這裏使用了引入js的方法,還可使用webpack打包的方法,把全部的js文件打包到同一個文件中,最後的結構相似這樣: (這裏有相關方法) github
<html> <head> <meta charset="utf-8"> <title>Add style to React</title> </head> <body> <div id="content" /> <script src="public/bundle.js" type="text/javascript"></script> <span style="float:center">Yo!</span> </body> </html>
JSX也是Facebook團隊提出的一個語法方案,它能夠在JavaScript的代碼中直接使用HMTL標籤來編寫JavaScript對象。它是一個相似於XML的JavaScript語法擴展(JSX的全稱即爲JavaScriptXML),這種語法方案須要經過JSXTransformer來進行編譯轉換成真實可用的JavaScript代碼。web
React是基於組件的開發思想,它認爲組件是一個徹底獨立的沒有任何其餘依賴的模塊文件,一個組件中能夠有本身的樣式(Inline Style)和結構(JSX編寫的HTML)。 segmentfault
React使用JSX來代替常規的JavaScript,由於使用JSX後執行地更快,用它編寫模版也很是簡單。
基本語法以下:
1. 使用JSX來建立一個HTML標籤,首字母小寫:
var link = <href="#">Hello World</a>
注意:這即是JSX語法,若是使用JavaScript,那麼link變量值不多是一個標籤!!!
上面的這句代碼實際上至關於調用了React.createElement('a',{href:'#'},'Hello World!');因而咱們能夠看到React.createElement()方法接收三個參數:‘標籤的名稱’,{屬性的名稱:屬性值},'標籤的內容'。(注:顯然React.createElement()方法是JavaScript語法,而var link = <href="#">Hello World</a>是JSX語法。具體咱們能夠這樣使用:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>react.js</title> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script> <script src="http://static.runoob.com/assets/react/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> var link = <a href="#">Hello World</a>; ReactDOM.render( link, document.getElementById('example') ); </script> </body> </html>
關於ReactDOM.render()方法後面會講到,大體上說它是一個將html元素渲染的方法。
咱們在https://babeljs.io/repl/這個網站上能夠在線將jsx代碼轉化爲js代碼,這裏將上面的js代碼轉化以下:
"use strict"; var link = React.createElement( "a", { href: "#" }, "Hello World" ); ReactDOM.render(link, document.getElementById('example'));
能夠看到,原生的js代碼來使用起來更加的麻煩,這也是使用jsx語法的最大好處和動因。
2.使用JSX來建立一個Component(組件,後面會詳細講解),首字母大寫:
var HelloWorld = <HelloWorld foo="bar"></HelloWorld>
注意:上面之因此嚴格要求區分首字母的大小寫,這是由於這樣JSX能夠很簡單的經過區分首字母的大小寫來判斷轉換的是HTML標籤仍是自定義的Component標籤。就像var a=5; 這裏a顯然是Number類型的,而var a = 'hello'; 顯然這裏的a就是string類型的,這樣咱們就無需再去判斷了,從而更加簡便。
3.JSX能夠經過{變量名}這種形式來插入一個JavaScript變量。以下所示:
var variable = "World"; <a href="#"> hello {variable}!</a>
因而咱們居然看到JavaScript語法和HTML語法完美結合!
4.剛剛說了能夠經過{變量名}來插入一個JavaScript變量,實際上,咱們還能夠經過{一個一次就能執行完的語句}在JSX中插入一個一次就能執行完成的JavaScript代碼。也就是說:咱們能夠在JSX中使用JavaScript表達式,但表達式必定要寫在{}中。以下所示:
var link = <a href="#"> Hello {conditions ? 'zzw':''}! </a>;
因爲這是JSX語法,須要編譯,編譯以後獲得的就是以下語法(顯然編譯獲得的JS語法):
var link = React.createElement('a',{href:'#'},if(conditions){zzw});
因而咱們能夠獲得這樣的一個結論:JSX的基本語法規則爲:遇到HTML標籤(以<開頭),就用HTML規則解析;遇到代碼塊(以{開頭)就用JavaScript規則解析。
5.1 以前所說的都是單個標籤的狀況,若是有多個(語句)呢?這時應當注意:不管你的JSX代碼有多長,每一段代碼都只能有一個根節點,不然編譯經過不了,以下所示:
var test = ( <button>點擊</button> <h1>錯誤的語法</h1> ); var test = ( <div> <button>點擊</button> <h1>正確的語法</h1> </div> );
5.2 咱們更經常使用的是ReactDOM.render()方法(這個方法也是JSX語法),它接受兩個參數:第一個參數時html元素,如<h1>哈哈</h1>;第二個參數是獲取一個元素,即要將第一個參數插入的地方,如document.getElementById("#ha");具體舉例以下所示:
ReactDOM.render( <div> <h1>JSX學習</h1> <h2>React 學習</h2> <p data-myattribute = "somevalue">這是一個很不錯的 JavaScript 庫!</p> </div> , document.getElementById('example') );
值得注意的是:這裏咱們添加了自定義屬性data-myattribute,且添加自定義屬性時必定要添加data-前綴。
6.由於JSX能夠直接將HTML寫在JavaScript代碼中,因此對於HTML中的屬性可能會和JavaScript的關鍵字衝突,爲避免衝突,咱們必須作出相應的轉變,如HTML的類class須要在JSX中寫成className, 而for須要轉化成htmlFor。
7. 以前咱們說過:React是基於組件的開發思想,它認爲組件是一個徹底獨立的沒有任何其餘依賴的模塊文件,一個組件中能夠有本身的樣式(Inline Style)和結構(JSX編寫的HTML)。
而以前咱們已經介紹了使用JSX來直接編寫HTML,這裏咱們將會把樣式添加到這裏組件中,舉例以下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>react.js</title>
<script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script>
<script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script>
<script src="http://static.runoob.com/assets/react/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
var myStyle = {
fontSize: 100,
color: '#FF0000'
};
ReactDOM.render(
<h1 style = {myStyle}>react學習</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
這裏應當知道:mystyle是一個對象,因此var myStyle = 後面用的是花括號。 定義的inline_style對象中的屬性名(key)就是樣式的屬性,若是該屬性有「-」,那麼咱們應當將之轉化爲駝峯式,如本例中的fontSize,不須要寫px,對於數字,會自動加上px,固然直接寫成fontSize:100px'; 雖然這裏把樣式寫成了內聯的形式(在組件內部)違反告終構、表現相分離的原則,可是它卻解決了由於分離帶來的組件獨立性的問題。
8. JSX支持組件的命名空間。
9.代碼風格建議:爲了有更好的可讀性,不管是單行語句仍是多行語句,都建議使用()來包裹JSX語句。
組件是React的核心部分。
先看下面的這個例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>react.js</title> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script> <script src="http://static.runoob.com/assets/react/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> var MyComponent = React.createClass({ render:function(){ return <h1> hello {this.props.name}! </h1> } }); ReactDOM.render( <MyComponent name="zhenwei"/>, document.getElementById('example') ); </script> </body> </html>
上面的代碼中,變量MyComponent就是一個組件類。 模版插入<MyComponent/>(注意這裏不須要寫成‘開始標籤+結束標籤’的形式)時,就會自動生成MyComponent的一個實例,且全部的組件類都須要有本身的render方法,用於輸出組件(即由render方法肯定輸入的組件實例的形式)。
而其中的props是指全部的屬性的集合(即屬性properties的縮寫形式),能夠看做一個數組對象,本例的name只是props中的其中一個屬性,還能夠有其餘的屬性,以下例所示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>react.js</title> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script> <script src="http://static.runoob.com/assets/react/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> var MyComponent = React.createClass({ render:function(){ return <h1> hello {this.props.name} , you are {this.props.gender} ! </h1> } }); ReactDOM.render( <div> <MyComponent name="zhenwei" gender="male"/> <MyComponent name="heting" gender="female"/> </div>, document.getElementById('example') ); </script> </body> </html>
最終咱們能夠看到效果以下:
值得注意的是:在ReactDOM.render()中的兩個組件實例必須由div包裹起來,由於在第一個參數中不得有兩個根元素,不然會報錯,以下面的形式就是錯的:
ReactDOM.render( <MyComponent name="zhenwei" gender="male"/> <MyComponent name="heting" gender="female"/> , document.getElementById('example') );
報錯以下:
function MyComponent (props){ return <h1> hello {props.name} , you are {props.gender} </h1> ; }
咱們能夠將React的組件當作是一個狀態機,一開始有一個初始狀態,這時有一個對應的UI;而後用戶和頁面互動以後,致使狀態發生了改變,從而觸發重新渲染UI。以下例所示:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>React 實例</title> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script> <script src="http://static.runoob.com/assets/react/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> 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') ); </script> </body> </html>
顯然,在上面的代碼中LikeButton是一個組件,其中getInitialState方法是固有的、React給咱們提供的方法,用於定義這個「狀態機」的初始狀態,這個狀態是一個對象,且咱們能夠經過this.state來改變;而handleClick方法是說當咱們點擊時,會自動切換兩種狀態。
這裏須要注意的是:
該屬性不一樣於this.props,它表示組件的全部子元素節點。而且React提供了一個方法即React.Child.map方法來遍歷子元素節點,而不用擔憂this.props.children是undefined類型(當組件沒有元素子節點時)、仍是object類型(當組件有一個元素子節點時)、或者是array類型(當組件有兩個及以上的元素子節點時)。由於React.Child.map方法能夠很好地處理各類狀況,舉例以下所示:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>React 實例</title> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script> <script src="http://static.runoob.com/assets/react/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> var MyComponent = React.createClass({ render:function(){ return ( <ol> { React.Children.map(this.props.children,function(child){ return <li>{child}</li>; }) } {/*凡是出現js代碼塊的地方,咱們都須要在外圍添加 {} ,來告訴React如何去解析*/} </ol> ); {/*這裏的return是一個語句,因此最後要添加分號*/} } }); ReactDOM.render( <MyComponent> <span>這是react</span> <span>這是JSX</span> <span>這是JavaScript</span> </MyComponent> , document.body ); </script> </body> </html>
注意
用戶在表單中填入內容,這就是用戶跟組件的互動,因此不能用this.props讀取,由於咱們以前說過「this.props表示那些一旦定義,就不能再改變的特性,而this.state是會隨着用戶互動而產生變化的特性」。因此這裏要互動,就得使用this.state來跟組<!DOCT<html>
<head> <meta charset="UTF-8" /> <title>React 實例</title> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script> <script src="http://static.runoob.com/assets/react/browser.min.js"></script> </head> <body> <script type="text/babel"> var Input = React.createClass({ getInitialState: function() { return {value: ''}; }, handleChange: function(event) { this.setState({value: event.target.value}); }, render: function () { var value = this.state.value; var myStyle={ width:'500px', height:'50px', fontSize:25, backgroundColor:'#ccc' }; return ( <div> <input type="text" value={value} style={myStyle} onChange={this.handleChange} /> <h1>I will repeat the input:{value}</h1> </div> ); } }); ReactDOM.render(<Input/>, document.body); </script> </body> </html>
React.createClass方法中由於包含的是JavaScript代碼,因此須要用{}括起來,咱們也能將之看做一個對象,有三個屬性,而這三個屬性又都是三個方法。
其中getInitialState()方法用來設置初始狀態;而handleChange()方法是用來處理change事件的,change事件被觸發時,就會將event.target.value設置位當前的狀態,而event.target即爲觸發這個事件的html元素,本例中即爲input元素; 而render方法則是必須的,用來告訴瀏覽器如何將這個組件渲染,最終效果以下所示:
組件的生命週期能夠分爲如下三個狀態:
React爲每種狀態提供了兩種處理函數,will函數在進入狀態以前使用,did函數在進入狀態以後使用,三種狀態能夠有五種處理函數,以下所示:
另外React還提供了兩種特殊狀態的處理函數:
下面是一個與之相關的例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>react.js</title>
<script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script>
<script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script>
<script src="http://static.runoob.com/assets/react/browser.min.js"></script>
<style>
.my_own_class{
font-size: 25px;
color:red;
}
</style>
</head>
<body>
<div id="container">
<!-- This element's content will be replaced by your component. -->
</div>
<script type="text/babel">
var Hello = React.createClass({
getInitialState:function(){
alert("init");
return {
opacity:1.0,
fontSize:'22px',
color:'red'
};
{/*關鍵:上面返回的值咱們通常能夠經過this.state獲得,顯然,這樣獲得的是一個對象。*/}
},
render:function(){
return <div style={this.state} > Hello ,{this.props.name} </div>
},
componentWillMount:function(){
alert("will");
},
componentDidMount:function(){
alert('did');
var _self = this;
{/*這裏之因此要把this賦值給_self,是由於這以前this指的是組件實例;而在window.setTimeout函數中時,this就指向了global全局環境,因此須要把this賦值給_self*/}
window.setTimeout(function(){
_self.setState({
opacity:0.3,
fontSize:'50px',
color:'blue'
});
},1000);
{/*顯然,這一句代碼被執行時,就處在了updating階段*/}
}
});
{/* 注意:props一旦定義,通常不可再變化;然而state仍是能夠不斷變化的。 */}
ReactDOM.render(
<Hello name="zhuzhenwei" />,
document.getElementById("container")
);
</script>
</body>
</html>
這一部份內容較爲重要,咱們能夠參考慕課網視頻,點擊進入。
咱們經過下面的這個例子來學習這一部分的知識內容,以下所示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>react.js</title> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script> <script src="http://static.runoob.com/assets/react/browser.min.js"></script> <style> </style> </head> <body> <div id="container"> <!-- This element's content will be replaced by your component. --> </div> <script type="text/babel"> var TestClickComponent = React.createClass({ handleClick:function(event){ var tipE=React.findDOMNode(this.refs.tip); {/* 上面這行代碼的做用是拿到ref="tip" 的span的真實節點,其中 this.refs.tip只是虛擬節點,只有使用React.findDOMNode()方法才能夠獲得其真實節點。須要格外注意大小寫,由於JSX是嚴格區分大小寫的。*/} if(tipE.style.display==='none'){ tipE.style.display='inline-block'; }else{ tipE.style.display='none'; } event.stopPropagation(); event.preventDefault(); }, render: function(){ return ( <div> <button onClick={this.handleClick}>顯示|隱藏</button><span ref="tip">測試點擊</span> </div> ); } }); var TestInputComponent = React.createClass({ getInitialState:function(){ return { inputContent:'' }; }, changeHandler:function(event){ this.setState({ inputContent: event.target.value }); {/*注意:this.setState()函數必定是須要在圓括號內添加花括號的,而後再添加須要設置的狀態state*/} event.stopPropogation(); event.preventDefault(); }, render: function(){ return ( <div> <input type="text" onChange={this.changeHandler}/> <span>{this.state.inputContent}</span> {/*這裏綁定了onChange事件(因爲這個虛擬節點,因此和純粹的html是不一樣的),注意區分大小寫。且一旦發生了onChange事件,就會回調this.changeHandler函數*/} </div> ); } }); React.render(<div><TestClickComponent/><br/><br/><br/><TestInputComponent/></div>,document.getElementById('container')); {/* 注意:第一:React.render()函數中的第一個參數必須只能有一個頂層標籤,因此咱們須要使用div包裹起來。 第二:這裏咱們使用了三個<br/>,這是爲了在實驗時更加地清楚,可是這違背了最佳實踐---樣式和結構的徹底分離,在作項目的過程當中,咱們千萬不能這麼作! */} </script> </body> </html>
須要注意的地方在代碼的註釋中講述的很是清楚。關於更多如何獲取真實的節點能夠看這篇文章。
咱們知道JSX是js的擴展,須要經過Babel編譯以後才能使用。在以前的例子中,咱們直接把JSX寫在了<script type="text/babel"></script>之間,這樣其自身就能夠轉換了。
固然咱們也能夠手動轉換,而後將JavaScript代碼直接寫在<script type="text/javascript"></script>之間。舉例說明以下:
第一步:將第八部分的JSX代碼複製粘貼到 http://babeljs.io/ 中,在右半部分就能夠獲得js代碼了。
第二步:將js代碼粘貼到<script type="text/javascript"></script>之間,便可正常使用。
參考資料
http://www.ruanyifeng.com/blog/2015/03/react.html
http://www.runoob.com/react/react-tutorial.html
http://www.tuicool.com/articles/r2IJNr
https://facebook.github.io/react/docs/introducing-jsx.html
https://www.tutorialspoint.com/reactjs/
推薦視頻
http://www.imooc.com/u/102030/courses?sort=publish
https://segmentfault.com/a/1190000007828811