第4章 數據流
- 由于react的數據流向是單向的(其父節點傳遞到子節點),
- 因此組件是簡單且易于把握的(它們只需要從父節點獲取props渲染即可)
- 假如頂層組件的某個prop改變了,react會遞歸地向下遍歷整個組件樹,重新渲染所有使用這個屬性的組件。
- react組件內部還具有自己的狀態,這些狀態只能在組件內修改。react組件本身很簡單,你可以把它們看成是一個函數,它接受props和state作為參數,返回一個虛擬的dom表現。
Props(properties 特性)
用途:可以把任意類型的數據傳遞給組件
2種方式設置props:
- 掛載組件時:
<ListSurveys surveys={surveys}/>
- 調用組件實例的setProps方法:
listSurveys.setProps({ surveys: survey });
setProps注意點:
- 只能在子組件上或組件樹外調用setProps
- 千萬別調用this.setProps或者修改this.props(一個組件絕對不可以修改自己的props)、
- 有需要請使用state!!!
可以通過this.prpos訪問props,但絕不能通過這種方式修改它。一個組件絕對不可以修改自己的props。
在jsx中,可以把props設置為字符串:
<a href="http://www.molinblog.com">molinblog</a>
也可以使用{}語法來設置,注入JavaScript傳遞任意類型的變量:
<a href={'http://www.molinblog.com/blog/' + blog.id}>{blog.title}</a>
還可以使用JSX的展開語法把props設置成一個對象:
render () {var props = {one: 'foo',two: 'bar'};return (<SurveyTable {...props} />)
}
props還可以用來添加事件處理程序:
render () {return (<a className='button save' onClike={this.handleClick}>Save</a>);
}
handleClick: function() {// ...
}
PropsTypes
- 用途:通過在組件中定義一個配置對象,來驗證props的方式
- 在應用中使用PropsTypes并不是強制性的,但這提供了一種極好的方式來描述組件的API
class SurveyTableRow extends React.Component {propsType: {survey: React.PropTypes.number.shape({id: React.PropTypes.number.isRequired}).isRequired,onClick: React.PropTypes.func},// ...
}
一臉黑線?????????、、
getDefaultProps
- 用途:設置屬性的默認值(針對那些非必需屬性)
- getDefaultProps不是在組件實例化時被調用,而是在React.createClass調用時就被調用了,返回值被緩存起來。也就是說,不能在getDefaultProps中使用任何特定的實力數據
- 在ES6中為屬性:defaultProps(可以標識static定義在class內,也可以定義在class外)
- 在ES5中為方法:getDefaultProps: function(){return {name:value}};
es5中使用示例:
var NewDom = React.createClass({//類名一定要大寫開頭getDefaultProps: function() {//設置默認屬性return {title:'133'};},propTypes: {title:React.PropTypes.string,},//屬性校驗器,表示必須是stringrender: function() {return <div>{this.props.title}</div>;//變量用花括號標識}
});
es6中使用示例:
const React = require('react');
const ReactDOM = require('react-dom');import {Promise} from 'es6-promise'class NewDom extends React.Component{//不能再組件定義的時候定義一個屬性render() {return <div >{this.props.title}</div>;}//開頭花括號一定要和小括號隔一個空格,否則識別不出來
}
//es6 這兩個屬性不能寫在class內。
NewDom.propTypes={//屬性校驗器,表示改屬性必須是string,否則報錯title: React.PropTypes.string,
}
NewDom.defaultProps={title:'fsdfd133'};//設置默認屬性ReactDOM.render((<NewDom></NewDom>
), document.querySelector('#init'))
state
- 每個react組件都會有自己的state,state與props的區別在于:state只存在于組件的內部
- state可以用來確定一個元素的視圖狀態。
- state可以通過setState修改,只要setState被調用,render就會被調用。
- 如果render函數的返回值有變化,虛擬DOM就會更新,真實的DOM也會被更新,最終用戶就會在瀏覽器中看到變化。
- 千萬不能直接修改this.state,永遠記得要通過this.setState方法修改。
放在state和props的各是哪些部分?
- state中應存那些簡單的組件正常工作時的必須要的數據。(布爾值,輸入框值等)
- 不要嘗試把props復制到state中,要盡可能把props當作數據源
總結
- 使用了props在整個組件樹中傳遞數據和配置
- 避免在組件內部修改this.props或調用this.setProps,請把props當作是只讀的
- 使用props來做事件處理器(下一章會細節化),與子組件通信
- 使用state存儲簡單的視圖狀態,比如下拉框是否可見這樣的狀態
- 使用this.setState來設置狀態,而不要使用this.state直接修改狀態
第5章 事件處理
展示頁面+js響應事件=用戶界面整體設計
綁定事件處理器
react處理的事件本質和原生js一樣(包括命名)
jsx版:
<button className="btn btn-save" onClick={this.handleSave}>Save</button>
js版
React.DOM.button({className: "btn btn-save", onClick: this.handleSaveClicked}, "Save");
jsx的寫法類似HTML內聯時間處理器屬性,比如onClick,但其實在底層實現上并沒有使用HTML的onClick屬性(而是通過事件處理之類的方法?)。
react對各類事件類型提供良好的支持,具體支持列在這里
其中絕大部分事件不需要額外的處理就能工作,但是觸控事件需要通過調用以下的代碼手動啟用:
React.initializeTouchEvents(true) // 是否已被改動????
事件和狀態
解決組件隨著用戶輸入而改變的問題,經過特定組件渲染后,綁定的事件處理器方法負責處理行為。
根據狀態進行渲染
可以在render中讀取this.state,然后根據this.state的值渲染出不同的頁面。
更新狀態
更新組件狀態有兩種方案:組件的setState方法和replaceState方法。replaceState用一個全新的state對象完整地替換掉原有的state。使用不可變數據結構來表示時,這種方式很有效,不過很少應用于其他場景下。
??永遠不要嘗試通過setState或者replaceState以外的方式去修改state對象。類似this.saveInProgress = true通常不是一個好主意,因為它無法通過React是否需要重新渲染組件,而且可能會導致下次調用setState時出現意外結果。
本節可參考極客學院
事件對象
使用event.target.value可以獲取表單中input值。
事件處理程序通過 合成事件(SyntheticEvent)的實例傳遞,SyntheticEvent 是瀏覽器原生事件跨瀏覽器的封裝。SyntheticEvent 和瀏覽器原生事件一樣有 stopPropagation()、preventDefault() 接口,而且這些接口夸瀏覽器兼容。
如果出于某些原因想使用瀏覽器原生事件,可以使用 SyntheticEvent的nativeEvent 屬性獲取。
本節可參考極客學院
總結
從用戶輸入到更新用戶界面,處理步驟非常簡單:
- 在react組件上綁定事件處理器
- 在事件處理器當中更新組件的內部狀態。組件狀態的更新會出發重繪
- 實現組件的render函數用來渲染this.state的數據
第6章 組件的復合
傳統HTML當中,元素是構成頁面的基礎單元。在React中,React組件是構成頁面的基礎單元。
本質上,一個組件就是一個JavaScript函數,它接受屬性(props)和狀態(state)作為參數,并輸出渲染好的HTML。組件一般被用來呈現和表達應用的某部分數據,因此你可以把react組件理解為HTML元素的擴展。
擴展HTML
React加jsx是強大而富有表現力的工具,允許我們使用類似HTML的語法創建自定義元素。比起單純的HTML,它們還能夠控制生命周期中的行為。
React偏愛符合,即通過結合小巧的、簡單的組件和數據對象,構造大而復雜的組件。React組件使不可以擴展的,而是通過組件之間的組合來構建應用。
組件復合的例子
組合模式的特征:選擇題組件有一個單選框,單選框有一個輸入框元素Input。
組裝HTML
對于每一個非必需的屬性都需要一個默認值,可以把它添加到defaultProps中。
追蹤狀態
組件需要記錄隨時間而變化的數據。
整合到父組件中
將子組件放到父組件中
父組件、子組件關系
子組件與其福組件通信的最簡單方式就是使用屬性(props)。父組件可以通過屬性傳入一個毀掉函數,子組件在需要時進行調用。
總結
組件的復合知識React提供的用于定制和特殊化組件的方式之一。
可通過本章的例子深入了解組件的復合。page44~52
第7章 mixin
mixin允許我們定義可以在多個組件中公共用的方法。
什么是mixin
mixin相當簡單,他們就是混合進組件類中的對象而已。React在這方面實現得更加深入,它能防止靜默函數覆蓋,同時還支持多個mixin混合。
以component開頭的生命周期函數,如componentDidMount,會按照在mixin數組中定義的順序被調用,并最終調用組件中定義的componentDidMount,如果它存在的話。
關于mixin的其它用法可參考:
- 一個監聽事件并修改state的mixin(如flux store mixin)。
- 一個上環mixin,它負責處理XHR上傳請求,同時將狀態以及上傳的進度同步到state
- 渲染層mixin,簡化在<\/body>之前渲染子元素的過程(如渲染模態對話框)
總結
mixin是解決代碼段重復的最強大工具之一,它同時還能讓組件保持專注于自身的業務邏輯。mixin允許我們使用強大的抽象功能,甚至有些問題如果沒有mixin就無法被優雅地解決。
即使我們只打算在單個組件中使用一個mixin,它還是為我們提供了描述一個特定行為或角色并提供給該組件的能力。mixin減少了我們在了解整個組件之前需要閱讀的代碼量,同時允許我們在不污染組件本身的情況下做一些丑陋的處理(比如管理內部__interval)。