React.js深刻學習詳細解析

目錄:

1、JSX介紹 javascript

2、React組件生命週期詳解 html

3、屬性、狀態的含義和用法 java

4、React中事件的用法 react

5、組件的協同使用 git

6、React中的雙向綁定 github

 1、JSX介紹 算法

①定義 編程

JSX=JavaScript XML,是一種在React組件內部構建標籤的類XML語法。React在不使用JSX的狀況下同樣能夠工做,可是使用JSX能夠提升組件的可讀性,加強JS語義,結構清晰,抽象程度高,代碼模塊化。所以推薦在React中使用JSX。 數組

②特色 安全

一、元素名首字母大寫

二、符合嵌套規則

三、能夠寫入求值表達式

四、駝峯式命名

五、不能使用javascript原生函數的一些關鍵詞,如for和class。須要替換成htmlFor和className

③使用方法

一、使用動態值:JSX將兩個花括號之間的內容{...}渲染爲動態值,花括號指明瞭一個javascript上下文環境,花括號裏面能夠是一個變量,也能夠是函數。 例如:

複製代碼
var name=「winty」; <p>{name}</p>

function date(d){
  return [
    d.getFullYear(),
    d.getMonth()+1,
    d.getDate()
  ].join('-);
};
<p>{date(new Date()}</p>
複製代碼

2.註釋:首先,在子節點中註釋要用大括號包裹起來,而後就能夠單行註釋/**/,也能夠多行註釋//。

複製代碼
var Hello=React.createClass({ render:function(){ return <p name="winty"> //set name  Hello ,World /* 多行註釋 多行註釋 */ </p>  } });
複製代碼

3.使用CSS內聯樣式

var style={ color:#000; }; React.render(<div style={style}>....</div>,document.body);

4.使用條件判斷

複製代碼
//方法1,三目運算符 var Hello=React.createClass({ render:function(){ return <p>Hello,{this.props.name?this.props.name : "LuckyWinty"}</p>  } }); //方法2,if-else語句 var Hello1=React.createClass({ getName:function(){ if(this.props.name) return this.props.name; else return "LuckyWinty"; render:function(){ return <p>Hello,{this.getName}</p>  } }); //方法3,使用邏輯||運算符 var Hello3=React.createClass({ render:function(){ return <p>Hello,{this.props.name||"LuckyWinty"}</p>  } });
複製代碼

④非DOM屬性介紹

JSX中有3個非DOM屬性,分別是:dangerouslySetInnerHTML、ref、key。

dangerouslySetInnerHTML:在JSX中直接插入HTML代碼,可是若是能避免使用這個屬性則儘可能避免使用。

不合時宜的使用 innerHTML 可能會致使 cross-site scripting (XSS) 攻擊。 淨化用戶的輸入來顯示的時候,常常會出現錯誤,不合適的淨化也是致使網頁攻擊 的緣由之一。

在完全的理解安全問題後果並正確地淨化數據以後,生成只包含惟一 key __html 的對象,而且對象的值是淨化後的數據。例如:

function createMarkup() { return {__html: 'First &middot; Second'}; }; <div dangerouslySetInnerHTML={createMarkup()} />

ref:父組件引用子組件,你能夠經過在屬性中設置指望的引用名來定義一個引用。例如:

複製代碼
... render:function(){ return <div>
           <input ref="MyInput" .../>
           </div> } ... //而後你就能夠在組件中的任何地方使用this.refs.myInput獲取這個引用了
複製代碼

key:是一個可選的惟一標識符,經過給組件設置一個獨一無二的鍵,並確保它在一個渲染週期中保持一致,使得React可以更只能地決定應該重用一個組件仍是銷燬並重建一個組件,進而提升渲染性能。例如:

複製代碼
var Hello3=React.createClass({ render:function(){ return <ul>
                <li key="1">1</li>
                <li key="2">2</li>
                <li key="3">3</li>
         </ul>  } });
複製代碼

更多詳細信息請參考:http://facebook.github.io/jsx/

2、React組件生命週期詳解

組件本質上就是狀態機,輸入肯定,輸出必定肯定。狀態和結果一一對應,從而使程序變得直觀。狀態發生轉換時會觸發不一樣的鉤子函數,從而讓開發者有機會作出響應。能夠用事件的思路來理解狀態,可是事件與事件之間互相獨立,可是不一樣狀態之間可能會互相影響。
組件的全部狀態結合起來就成了組件的生命週期。即:初始化階段->運行中階段->銷燬階段。
 
不一樣生命週期內能夠自定義的函數
初始化階段:
①getDefaultProps:獲取默認屬性,只調用一次,是在createClass以後調用的。實例之間共享引用
②getInitialState:初始化每一個實例的特有初始化狀態
③componentWillMount:mout就是裝載的意思,這個方法的意思就是說組件即將被裝載到頁面中,也是render以前最後一次修改狀態的機會
④render:組件在render函數生成虛擬節點,最後由react將虛擬節點變成真正的節點渲染到頁面上。只能訪問this.props和this.state,只有一個頂層組件,最好不要修改狀態和DOM輸出。
⑤componentDidMount:組件被裝載後纔會被調用,也就是說調用這個方法的時候,組件已經被渲染到了頁面上,這個時候能夠修改DOM
這五個函數的執行順序就是從上到下的。須要注意的是getDefaultProps只會在組件的第一個實例被初始化的時候被調用,也就是說第二個實例以後都是從getInitialState開始調用。同一個組件的全部實例的默認屬性都是同樣的。
主要測試代碼:
複製代碼
<script type="text/babel"> var Hello=React.createClass({ getDefaultProps:function(){ console.log("getDefaultProps, 1"); }, getInitialState:function(){ console.log("getInitialState, 2"); return null; }, componentWillMount:function(){ console.log("componentWillMount, 3"); }, render:function(){ console.log("render, 4"); return <p>Hi,LuckyWinty!</p>  }, componentDidMount:function(){ console.log("componentDidMount, 5"); }, }); React.render(<Hello></Hello>,document.body);
</script>
複製代碼

運行結果:

運行中階段:
①componentWillReceiveProps:這個函數在組件即將接收到屬性時觸發的,或者是父組件的屬性發生變化時,屬性在傳送到組件以前,開發者有機會經過這個函數去處理屬性。好比修改,更新內部狀態等。
②shouldComponentUpdate:當組件接收到新屬性或者新狀態的時候觸發的。這個是一個疑問函數,也就是說咱們能夠告訴react不去更新某個組件。由於有時候屬性或者狀態並不會致使組件發生更新。在組件不須要更新的狀況下,手動使shouldComponentUpdate返回false,這樣react就不須要再通過render和diff算法去判斷是否要更新,從而提升性能。
③componentWillUpdate:render觸發以前觸發,更新組件,不能修改屬性和狀態
④render:組件在render函數生成虛擬節點,最後由react將虛擬節點變成真正的節點渲染到頁面上,只能訪問this.props和this.state,只有一個頂層組件,最好不要修改狀態和DOM輸出。
⑤componentDidUpdate:render以後,真正的DOM被渲染以後調用
備註:這五個函數的執行順序也是從上到下的。這個的測試代碼已上傳至:https://github.com/LuckyWinty/ReactStudyDemo,歡迎參考!
 
銷燬階段:
①componentWillUnmount:這個函數在銷燬操做真正執行以前調用,給開發者最後的機會進行一些清理工做。

3、屬性、狀態的含義和用法

屬性的含義:
props=properties,屬性是不能夠由組件本身進行修改的,組件的屬性是由父組件傳遞進來的。
屬性的用法:
1、鍵值對
<Hello name="winty"/>   字符串
<Hello name={123}/>    大括號包裹的求值表達式
<Hello name={[1,2,3]}/>   傳入數組
<Hello name={winty}/>   變量
2、展開定義(我的認爲就是對象式定義)
var props={ one:"123", two:"22" }
這樣定義的話,理論上使用應該是one={props.one}這樣調用,可是這樣寫起來比較繁瑣,並且若是數據被修改,就須要對應修改相應的賦值,而且沒法動態地設置屬性,因此react中添加了一種展開語法:
<Hello {...props}/>    //也就是三個點加上對象名稱。
這樣使用展開語法,react就會自動把對象中的變量和值看成是屬性的賦值,因此Hello實際上就拿到了one、two兩個屬性,若是沒有三個點的話,Hello拿到的實際上就是props對象,使用的時候還須要本身從中取出變量和值
3、調用react提供的setProps()函數(幾乎不用)
var instance=React.render(<HelloWorld></HelloWorld>,document.body);
instance.setProps({name:"winty"});
狀態的含義:
state,狀態是由事物自行處理、不斷變化的
狀態的用法:
getInitialState:初始化實例的狀態
setState:更新組件狀態,一旦更新了狀態,那麼就會觸發diff算法,檢查內容是否發生變化,如有變化則更新組件,不然就不用。
 
屬性和狀態對比
類似點:都是純JS對象、都會觸發render更新、都具備肯定性。
屬性和狀態區分:組件在運行時須要修改的數據就是狀態
 
4、React中事件的用法
事件處理函數:React綁定事件處理器的方法和HTML語法很是相似,全部的事件在命名上與原生的javascript規範一致,而且會在相同的情境下觸發。
編寫函數
handleClick:function(){
...
}
綁定
onClick={this.handleClick}
 
各種事件詳細說明:
①移動設備上的觸摸事件:onTouchCancel、onTouchEnd、onTouchMove、onTouchStart 
②鍵盤類事件:onKeyDown、onKeyPress、onKeyUp
③剪切類事件:onCopy、onCut、onPaste 
④表單類:onChange//內容變化即觸發、onInput//輸入框、onSubmit//禁止表單默認跳轉行爲
⑤事件:onFocus、onBlur 
⑥UI元素類:onScroll
⑦鼠標滾動事件:onWheel
⑧鼠標類型:onClick、onContextMenu//右鍵菜單、onDoubleClick //雙擊、onMouseDown、onMouseEnter、onMouseLeave、onMouseMove、onMouseOut、onMouseOver、onMouseUp
⑨拖拽事件:onDrop、onDrag、onDragEnd、onDragEnter、onDragExit、onDragLeave、onDragOver、onDragStart
事件對象介紹
使用方法:就是在編寫事件對象處理函數的時候,添加一個參數。拿到這個對象以後,就經過對象的屬性來能夠獲取一些信息。
例如:
handleChange:function(event){ console.log(event.target.value); }
示例中,event就是事件對象,event.target就是事件對象的屬性,就是對應的DOM元素,拿到這個元素以後再獲取它的值。
事件對象屬性
通用屬性:

 其餘不一樣類型的事件有不一樣的屬性,簡單瞭解一下

知道了事件的一些屬性,咱們就能夠很方便地在React中獲取這些屬性,進行一些邏輯的處理,實現一些複雜的業務功能、頁面效果等。

例如:咱們能夠利用鼠標事件屬性,實時顯示鼠標在某個區域的座標:

複製代碼
<script type="text/jsx"> var HelloWorld = React.createClass({ getInitialState: function () { return { x: 0, y: 0 } }, handleMouseMove: function (event) { this.setState({ x: event.clientX, y: event.clientY }); }, render: function () { return <div onMouseMove={this.handleMouseMove} style={{ height: '500px', width: '500px', backgroundColor: 'gray' }}> {this.state.x + ', ' + this.state.y} </div>;  }, }); React.render(<HelloWorld></HelloWorld>, document.body);
    </script>
複製代碼

5、組件的協同使用

組件協同使用的定義:組件的協同本質上就是對組件的一種組織、管理方式。
組件協同使用的目的:邏輯清晰、代碼模塊化、封裝細節、代碼可複用。
組件協同使用的方式:

①組件嵌套使用:也就是說,用一個父組件把子組件包裹起來,本質就是父子關係。以下圖描述:

實例代碼:

複製代碼
var React = require('react'); var CommentList=require('./CommentList.jsx'); var CommentForm=require('./commentFrom.jsx'); var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox">
        <h1>Comments</h1>
        <CommentList />   //這是一個組件
        <CommentForm />    //這是另外一個組件
      </div>  ); } }); module.exports = CommentBox;
複製代碼
父子組件之間的通訊:
父組件->子組件:經過屬性,父組件把數據經過屬性來傳遞給子組件
子組件->父組件:本質上,子組件不能向父組件通訊。可是能夠間接地經過觸發事件來通訊,也就是委託。
嵌套組合缺點:
父子關係的具體實現須要通過深思熟慮,貿然編寫將致使關係混亂、代碼難以維護
沒法掌握全部細節,使用者只知道組件用法,不知道實現細節,遇到問題難以修復

②Mixin:也就是能夠把相同的代碼抽象出來,封裝成一個函數,而後再調用。

Mixin的目的:橫向抽離出組件的類似代碼
類似概念:面向切向面編程、插件
實例代碼:
複製代碼
var Time=React.createClass({ mixins:[IntervalMixin(1000)], getInitialState:function(){ return {secondElapsed:0}; }, onTick:function(){ this.setState({secondElapsed:this.state.secondElapsed+1}); }, render:function(){ return ( <div>Seconds Elapsed:{this.state.secondsElapsed}</div>  ); } });
複製代碼

mixin至關簡單,它們就是混合進組件類中的對象而已。React在這方面實現得更加深刻,它能防止靜默函數覆蓋,同時還支持多個mixin混合。可是這些功能在別的系統中可能引發衝突。例如:

複製代碼
React.createClass({ mixins:[{ getInitialState:function(){ return {a:1}} }], getInitialState:function(){ return {b:2}} });
複製代碼

這樣在mixin和組件類中同時定義了getInitialState方法,獲得的初始state是{a:1,b:2}.若是mixin中的方法和組件類中的方法返回的對象中存在重複的鍵,React會拋出一個錯誤來警示這個問題。

 6、React中的雙向綁定

React創立的理念跟angular那些框架就是不一樣的,React是單向數據綁定的。那麼怎麼實現像angular那樣的雙向綁定效果呢?看代碼:

複製代碼
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>React中的雙向數據綁定</title>
</head>
<body>
    <script src="./react-0.13.2/react-0.13.2/build/react-with-addons.js"></script>
    <script src="./react-0.13.2/react-0.13.2/build/JSXTransformer.js"></script>
    <script type="text/jsx"> var BindingMixin = { handleChange: function(key) { var that = this var newState = {} return function(event) { newState[key] = event.target.value that.setState(newState) } } } var BindingExample = React.createClass({ mixins: [React.addons.LinkedStateMixin], getInitialState: function() { return { text: '', comment: '', } }, render: function() { return <div>
                    <input type="text" placeholder="請輸入內容" valueLink={this.linkState('text')} />
                    <textarea valueLink={this.linkState('comment')}></textarea>
                    <h3>{this.state.text}</h3>
                    <h3>{this.state.comment}</h3>
                </div>  } }) React.render(<BindingExample></BindingExample>, document.body);
    </script>
</body>
</html>
複製代碼

效果圖(沒有CSS樣式,有點不優雅,見諒):

更多學習demo已上傳至:https://github.com/LuckyWinty/ReactStudyDemo,歡迎參考!

參考資料:

    《React引領將來的用戶界面開發框架》

     極客學院視頻課程

 

PS:react.js模塊化開發及打包方式歡迎參考個人上一篇博文《React.js入門必須知道的那些事》,後續會有更多深刻的學習,歡迎你們給我學習意見^_^

相關文章
相關標籤/搜索