JSX:創建ReactElement的便捷寫法。(JS對象來表述DOM元素)
ReactElement:一種輕量級、無狀態、不可改變的DOM元素的虛擬表述。
Babel:讓你寫的爽支持最新ES6語法,
VertualDOM:JS對象來表述DOM元素
Flux : facebook提出的前端應用架構模式,核心概念是單向數據流
Dispatcher:
Action:JavaScript對象。信息載體
Store
Redux:是js的狀態容器,提供可預測的狀態管理。
1、單一數據源:整個應用的state存儲在js對象中,Redux使用store存儲整個state。
2、state是隻讀的。只能通過action修改
3、使用純函數執行修改
reducer:接收先前的state和action,返回新的state。reducer可以拆分爲多個,分別操作state的不同部分
reducer中,整個程序的數據存儲在唯一一個object中。
無狀態函數式組件
爲了創建純展示組件,這種組件只負責根據傳入的props來展示,不涉及到要state狀態的操作。
在大部分React代碼中,大多數組件被寫成無狀態的組件,通過簡單組合可以構建成其他的組件等;這種通過多個簡單然後合併成一個大應用的設計模式被提倡。
無狀態函數式組件形式上表現爲一個只帶有一個render方法的組件類,通過函數形式或者ES6 arrow function的形式在創建,並且該組件是無state狀態的。具體的創建形式如下:
function HelloComponent(props, /* context */) {
return <div>Hello {props.name}</div>
}
ReactDOM.render(<HelloComponent name="Sebastian" />, mountNode)
無狀態組件的創建形式使代碼的可讀性更好,並且減少了大量冗餘的代碼,精簡至只有一個render方法,大大的增強了編寫一個組件的便利,除此之外無狀態組件還有以下幾個顯著的特點:
1、組件不會被實例化,整體渲染性能得到提升
因爲組件被精簡成一個render方法的函數來實現的,由於是無狀態組件,所以無狀態組件就不會在有組件實例化的過程,無實例化過程也就不需要分配多餘的內存,從而性能得到一定的提升。2、組件不能訪問this對象
無狀態組件由於沒有實例化過程,所以無法訪問組件this中的對象,例如:this.ref、this.state等均不能訪問。若想訪問就不能使用這種形式來創建組件3、組件無法訪問生命週期的方法
因爲無狀態組件是不需要組件生命週期管理和狀態管理,所以底層實現這種形式的組件時是不會實現組件的生命週期方法。所以無狀態組件是不能參與組件的各個生命週期管理的。4、無狀態組件只能訪問輸入的props,同樣的props會得到同樣的渲染結果,不會有副作用
無狀態組件被鼓勵在大型項目中儘可能以簡單的寫法來分割原本龐大的組件,未來React也會這種面向無狀態組件在譬如無意義的檢查和內存分配領域進行一系列優化,所以只要有可能,儘量使用無狀態組件。
eg:
React當中的listview
React.createClass
React.createClass是react剛開始推薦的創建組件的方式,這是ES5的原生的JavaScript來實現的React組件,其形式如下:
const InputControlES5 = React.createClass({
propTypes: {//定義傳入props中的屬性各種類型
initialValue: React.PropTypes.string
},
defaultProps: { //組件默認的props對象
initialValue: ''
},
// 設置 initial state
getInitialState: function() {//組件相關的狀態對象
return {
text: this.props.initialValue || 'placeholder'
};
},
handleChange: function(event) {
this.setState({ //this represents react component instance
text: event.target.value
});
},
render: function() {
return (
<div>
Type something:
<input onChange={this.handleChange} value={this.state.text} />
</div>
);
}
});
InputControlES6.propTypes = {
initialValue: React.PropTypes.string
};
InputControlES6.defaultProps = {
initialValue: ''
};
React.Component
React.Component是以ES6的形式來創建react的組件的,是React目前極爲推薦的創建有狀態組件的方式,最終會取代React.createClass形式;相對於 React.createClass可以更好實現代碼複用。將上面React.createClass的形式改爲React.Component形式如下:
class InputControlES6 extends React.Component {
constructor(props) {
super(props);//在ES6中,在子類的constructor中必須先調用super才能引用this,super(props)的目的:在constructor中可以使用this.props
// 設置 initial state
this.state = {
text: props.initialValue || 'placeholder'
};
// ES6 類中函數必須手動綁定
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
text: event.target.value
});
}
render() {
return (
<div>
Type something:
<input onChange={this.handleChange}
value={this.state.text} />
</div>
);
}
}
InputControlES6.propTypes = {
initialValue: React.PropTypes.string
};
InputControlES6.defaultProps = {
initialValue: ''
};
1、只要有可能,儘量使用無狀態組件創建形式。
2、否則(如需要state、生命週期方法等),使用React.Component
這種es6形式創建組件
3、能用React.Component創建的組件的就儘量不用React.createClass形式創建組件。
state設計原則
最小化原則:創建儘量多的無狀態組件,這些組件唯一關心的是渲染數據。在這些組件的外層,應該有一個包含state的父組件。父組件專門助理各種事件、交流邏輯、修改state。子組件只關心傳入屬性。
DOM操作
大多數情況下使用setState更新UI。有些情況需要訪問DOM結構。
let 聲明變量,代碼塊內有效。適合for循環。
const:聲明常量,聲明後值不可變。變量名不指向數據,而是指向數據地址,數據可變地址不可變。
const foo={};
foo.prop=123;
foo.prop//123
foo={}//TypeError:“foo is read-only”
跨模塊常量
export const A=1;
全局變量
window.a=1;
let const聲明的不屬於全局變量
容器組件使用 connect() 方法連接 Redux
我們用 react-redux 提供的 connect() 方法將“笨拙”的 Counter 轉化成容器組件。connect() 允許你從 Redux store 中指定準確的 state 到你想要獲取的組件中。這讓你能獲取到任何級別顆粒度的數據。
讓我們看下,我們擁有一個 的展示組件,它有一個通過 props 傳過來的值,和一個函數 onIncrement,當你點擊 “Increment” 按鈕時就會調用這個函數:
import { Component } from 'react';
export default class Counter extends Component {
render() {
return (
<button onClick={this.props.onIncrement}>
{this.props.value}
</button>
);
}
}
containers/CounterContainer.js
import { Component } from 'react';
import { connect } from 'react-redux';
import Counter from '../components/Counter';
import { increment } from '../actionsCreators';
// 哪些 Redux 全局的 state 是我們組件想要通過 props 獲取的?
function mapStateToProps(state) {
return {
value: state.counter
};
}
// 哪些 action 創建函數是我們想要通過 props 獲取的?
function mapDispatchToProps(dispatch) {
return {
onIncrement: () => dispatch(increment())
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Counter);
connect後面第二個括號是要添加prop的react組件,第一個括號中的參數是用來改變該組件prop的方法,第一個括號有兩個參數,第一個參數是一個函數,返回一個對象,對象的鍵是該組件的prop屬性,值是該prop的值;第二個參數也是一個函數,返回一個對象,對象的鍵同樣是prop的屬性名,值是一個redux的dispatch,當這個prop屬性被用於觸發時,dispatch會改變redux中state的值。