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請求,請求新資料回來;
好了 由於時間的關係 入門學習一 先介紹這裡,後面繼續學習!