ReactJS入門學習一
閱讀目錄
React是什么?
React僅僅是VIEW層,而我們經常看到Angular是一個完整的框架,而React不是,因此我們看到他們兩個的側重點不一樣,所以也不能比較的,React提供了模板語法及一些函數鈎子用於HTML的渲染,只用於View層。
React的優點?
1. 虛擬DOM
在DOM樹的狀態發生改變時,虛擬DOM機制會將前后DOM樹進行對比,如果兩個DOM樹有不一樣的地方,那么React僅僅會對那些不一樣的區域來進行響應DOM修改,這也就是React的更高的性能是使用虛擬DOM來實現的。
2. 數據流
React實現了單向響應的數據流,從而減少了重復的代碼,這也是為什么比傳統數據綁定更簡單。
瀏覽器對React的支持程度:IE9- 以下的瀏覽器是不支持React.
下面我們來學習下React的基本使用方法吧!
首先React擅長於組件化頁面,我們來看看使用React來如何渲染頁面的,如下代碼:
首先需要在頁面上引入React.js
<script src="./build/react.min.js"></script>
HTML代碼結構如下:
<div id="content"></div>
JS代碼如下:
<script>
var CommentBox = React.createClass({
displayName: 'CommentBox',
render: function(){
return (
React.createElement('div',{className:'commentBox'},"Hello,world!I am a CommentBox")
);
}
});
React.render(
React.createElement(CommentBox,null),document.getElementById("content")
);
</script>
在頁面上生成代碼結構如下:

在IE9+ firefox chrome下生效;
我們下面來解釋下上面的代碼的含義:
React.createClass(): 該方法來創建一個新的React組件;其中最重要的方法是render,該方法返回一顆React組件樹,這棵樹將會渲染成HTML;
上面的div標簽不是真實的DOM節點,他們是React div組件的實例,我們可以認為React是通過此來如何處理標記或者一些數據,React是安全的,它不生成HTML字符串,所以默認阻止了xSS的攻擊;
React.render():該方法是 實例化根組件,啟動框架,它有第二個參數,含義是:注入標記到原始的DOM元素中;
React 不依賴與Jquery,因此上面是通過 document.getElementById(“content”)來作為React.render()的第二個參數,當然我們也可以使用jqeury的方式來作為第二個參數調用,但是我們必須如下這樣:$(“#content”)[0], 而不是 $(“#content”);
React如何制作組件?
如下我們有一個網站頁面:首頁分為如下幾塊,導航頁,側邊欄,還有內容區;假如我現在想導航頁,側邊欄和內容區都做成一個組件模塊,因為有很多頁面需要公用的;如下page頁面結構圖:

那么下面我們可以使用React.createClass()方法來創建一個react組件;如下代碼:
導航頁代碼如下:我們使用JSX來寫代碼如下:(切記頁面需要引入)
<script src="./build/react.min.js"></script>
<script src="./build/JSXTransformer2.js"></script>
這句代碼;這是目前測試的,方便點直接引入;
<script type="text/jsx">
/* 導航模塊代碼 */
var NavMode = React.createClass({
render: function(){
return (
<div className = "NavList">
Hello word! I am a Nav List
</div>
);
}
});
/* 側邊欄模塊代碼 */
var SlideMode = React.createClass({
render: function(){
return (
<div className="slideMode">hello world! I am a slide</div>
)
}
});
/* 內容區模塊代碼 */
var ContentMode = React.createClass({
render: function(){
return (
<div className="contentMode">Hello world! I am comtent</div>
)
}
});
/* 頁面div封裝 上面三個模塊 */
var page = React.createClass({
render: function(){
return (
<div className="homepage">
<h1>page首頁</h1>
<NavMode />
<SlideMode />
<ContentMode />
</div>
)
}
});
/* 初始化到content容器內 */
React.render(
React.createElement(page,null),document.getElementById("content")
);
</script>
頁面渲染完成后,查看如下演示:

因此在頁面也可以看到預覽效果;如上是根據JSX的語法來混合HTML的標簽來創建我們的組件的,JSX編譯器會自動重寫HTML標簽為React.createElement(tagName)表達式。
理解組件屬性props
Props表示的是組件自身的屬性,是父層節點傳遞給子層節點的一些屬性或者數據,比如我的上面的代碼,內容區,可能不同的模塊有不同的內容,因此我們需要有相同的模板ContentMode 根據參數的傳遞不同而顯示不同的內容;代碼如下:
/* 內容區模塊代碼 */ var ContentMode = React.createClass({ render: function(){ return ( <div className="ContentMode"> <div class="contents">{this.props.contents}</div> {this.props.children} </div> ) } }); /* 頁面div封裝 上面三個模塊 */ var Page = React.createClass({ render: function(){ return ( <div className="homepage"> <ContentMode contents ="longen">this is one comment</ContentMode > <ContentMode contents ="longen2">this is two comment</ContentMode > </div> ) } }); /* 初始化到content容器內 */ React.render( React.createElement(Page,null),document.getElementById("content") );
在頁面中顯示的DOM結構如下:

如上,我們從父節點Page傳遞給子節點ContentMode 的一些數據,從父節點傳遞到子節點的數據稱為 ”props”;
在JSX中通過javascript表達式放在大括號中(作為屬性或者子節點);我們訪問傳遞給組件的命名屬性作為 this.props的鍵,任何內嵌的元素作為this.props.children;
理解頁面中如何渲染數據的
比如發ajax請求等返回數據,現在我這邊是模擬靜態數據:如下返回數據:
var data = [{"name":'longen1',"age":'28'},{"name":'longen2',"age":30}];
現在我們要做的是 通過上面的data數據 分別渲染到content(內容區域去),第一步我們需要實例化根組件,調用React.render()方法;如下:
var data = [{"name":'longen1',"age":'28'},{"name":'longen2',"age":30}];
/* 初始化到content容器內 */ React.render( <ContentMode data={data} />, document.getElementById("content") ); 調用內容區域 ContentMode 模塊,代碼如下: /* 內容區模塊代碼 */ var ContentMode = React.createClass({ render: function(){ return ( <div className="ContentMode"> <h1>內容渲染進來</h1> <Page data={this.props.data} /> </div> ) } });
如上我們通過父層節點ContentMode 傳遞數據給子節點Page,Page模塊通過this.props取到父節點傳來的數據,再調用Page模塊,渲染數據,Page模塊渲染數據如下:
var Page = React.createClass({ render: function(){ var ContentModes = this.props.data.map(function(content){ return ( <p className="pline" data-age={content.age}>{content.name}</p> ) }); return ( <div className="homepage">{ContentModes}</div> ) } });
然后Page模塊通過自身屬性 this.props取到值后 進行map遍歷,如下頁面演示效果:

HTML代碼渲染成結構如下:

理解從服務器端獲取數據及理解state的
現在我們來新建一個page.json來存放json數據,數據如下:
[{"name":"我是龍恩我來測試數據1","age":"28"},{"name":"我是塗根華我來測試數據2","age":"30"}]
現在讓我們來從服務器端來獲取數據,我們先使用React.render()這個方法來初始化根組件;如下代碼:
/* 初始化到content容器內 */
React.render(
<ContentMode url="page.json" />, document.getElementById("content")
);
下面是所有的代碼如下:
var Page = React.createClass({ render: function(){ var ContentModes = this.props.data.map(function(content){ return ( <p className="pline" data-age={content.age}>{content.name}</p> ) }); return ( <div className="homepage">{ContentModes}</div> ) } }); /* 內容區模塊代碼 */ var ContentMode = React.createClass({ getInitialState: function(){ return {data:[]}; }, componentDidMount: function(){ $.ajax({ url: this.props.url, dataType:'json', success: function(data){ this.setState({data:data}); }.bind(this), error: function(xhr,status,err){ console.log(this.props.url,status,err.toString()); }.bind(this) }); }, render: function(){ return ( <div className="ContentMode"> <h1>內容渲染進來</h1> <Page data={this.state.data} /> </div> ) } }); /* 初始化到content容器內 */ React.render( <ContentMode url="page.json" />, document.getElementById("content") );
到目前為止:我們的每一個組件都是根據自己的props渲染了自己一次,props是不可變的,他們是從父節點傳遞過來的數據,但是呢,如果我們需要從服務器端更新數據的話,我們可以使用state來更新數據。this.state是組件私有的,我們可以通過this.setState() 來改變它,那么組件會重新渲染下自己。
現在我們來分析下上面的代碼:getInitialState()是在組件生命周期中僅執行一次,設置組件的初始化狀態。該方法是在React源碼中做了封裝的。
componentDidMount() 是一個組件被渲染的時候React自動調用的方法,該方法也是React源碼中封裝好了的,我們可以看到如上代碼在調用getInitialState()方法時,給data定義了一個空數組[]; 當調用componentDidMount() 方法時,通過發ajax請求(在此我們使用jquery來演示ajax),當有數據更新的時候,我們使用 this.setState({data:data}); 該方法,對數據data重寫賦值;從而改變原有的數據;然后使用新數據使UI自動更新;
在頁面上演示效果如下:

頁面HTML代碼渲染結構如下:

我們也可以仿照新浪微博那樣,每隔幾秒中自動刷新數據,這里我們可以使用簡單的setInterval()來輪詢下,當然我們可以使用更好的方法 WebSockets技術
代碼如下:
<script type="text/jsx">
var Page = React.createClass({
render: function(){
var ContentModes = this.props.data.map(function(content){
return (
<p className="pline" data-age={content.age}>{content.name}</p>
)
});
return (
<div className="homepage">{ContentModes}</div>
)
}
});
/* 內容區模塊代碼 */
var ContentMode = React.createClass({
getInitialState: function(){
return {data:[]};
},
loadServer: function(){
$.ajax({
url: this.props.url,
dataType:'json',
success: function(data){
this.setState({data:data});
}.bind(this),
error: function(xhr,status,err){
console.log(this.props.url,status,err.toString());
}.bind(this)
});
},
componentDidMount: function(){
this.loadServer();
setInterval(this.loadServer,this.props.pollInterval);
},
render: function(){
return (
<div className="ContentMode">
<h1>內容渲染進來</h1>
<Page data={this.state.data} />
</div>
)
}
});
/* 初始化到content容器內 */
React.render(
<ContentMode url="page.json" pollInterval={2000}/>, document.getElementById("content")
);
</script>
如上代碼,我們使它們每隔2秒鍾會發一次ajax請求,請求新數據回來;
好了 由於時間的關系 入門學習一 先介紹這里,后面繼續學習!
