react
Why React?
React is a JavaScript library for creating user interfaces by Facebook and Instagram. Many people choose to think of React as the V in MVC.We built React to solve one problem: building large applications with data that changes over time.
Simple
Declarative
Build Composable Components
In fact, with React the only thing you do is
build components
.
react的概念
組件
React 應(yīng)用都是構(gòu)建在組件之上骡苞,各個(gè)組件維護(hù)自己的狀態(tài)和 UI为肮,當(dāng)狀態(tài)變更扣唱,自動(dòng)重新渲染整個(gè)組件
import React, { Component } from 'react';
import { render } from 'react-dom';
class HelloMessage extends Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
props
和 state
props 就是組件的屬性,由外部通過 JSX 屬性傳入設(shè)置
state 是組件的當(dāng)前狀態(tài),可以把組件簡單看成一個(gè)“狀態(tài)機(jī)”车摄,根據(jù)狀態(tài) state 呈現(xiàn)不同的 UI 展示祟牲。一旦狀態(tài)(數(shù)據(jù))更改,組件就會(huì)自動(dòng)調(diào)用 render 重新渲染 UI榛搔,這個(gè)更改的動(dòng)作會(huì)通過this.setState 方法來觸發(fā)诺凡。原則:讓組件盡可能地少狀態(tài)。
組件就是通過這兩個(gè)屬性的值在 render 方法里面生成這個(gè)組件對應(yīng)的 HTML 結(jié)構(gòu)
相關(guān)函數(shù)
1践惑、裝載組件觸發(fā)
componentWillMount
只會(huì)在裝載之前調(diào)用一次腹泌,在 render 之前調(diào)用,你可以在這個(gè)方法里面調(diào)用 setState
改變狀態(tài)尔觉,并且不會(huì)導(dǎo)致額外調(diào)用一次 render
componentDidMount
只會(huì)在裝載完成之后調(diào)用一次凉袱,在 render 之后調(diào)用,從這里開始可以通過ReactDOM.findDOMNode(this)
獲取到組件的 DOM 節(jié)點(diǎn)
2侦铜、更新組件觸發(fā)
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
3专甩、卸載組件觸發(fā)
componentWillUnmount
組合組件
使用組件的目的就是通過構(gòu)建模塊化的組件,相互組合組件最后組裝成一個(gè)復(fù)雜的應(yīng)用钉稍。在 React 組件中要包含其他組件作為子組件涤躲,只需要把組件當(dāng)作一個(gè) DOM 元素引入就可以,通過 props 傳遞值贡未。
JSX
將 HTML 直接嵌入了 JS 代碼里面
<a >Hello!</a>
React.createElement('a', {href: 'http://facebook.github.io/react/'}, 'Hello!')
通過 React.createElement 來構(gòu)造組件的 DOM 樹种樱。第一個(gè)參數(shù)是標(biāo)簽名,第二個(gè)參數(shù)是屬性對象羞秤,第三個(gè)參數(shù)是子元素缸托。
利用 JSX 編寫 DOM 結(jié)構(gòu),可以用原生的 HTML 標(biāo)簽瘾蛋,也可以直接像普通標(biāo)簽一樣引用 React 組件俐镐。這兩者約定通過大小寫來區(qū)分,小寫的字符串是 HTML 標(biāo)簽哺哼,大寫開頭的變量是 React 組件佩抹。HTML 里的 class 在 JSX 里要寫成 className叼风,因?yàn)?class 在 JS 里是保留關(guān)鍵字。同理某些屬性比如 for 要寫成 htmlFor棍苹。
Virtual DOM
當(dāng)組件狀態(tài) state 有更改的時(shí)候无宿,React 會(huì)自動(dòng)調(diào)用組件的 render 方法重新渲染整個(gè)組件的 UI。組件 DOM 結(jié)構(gòu)就是映射到這個(gè) Virtual DOM 上枢里,React 在這個(gè) Virtual DOM 上實(shí)現(xiàn)了一個(gè) diff 算法孽鸡,當(dāng)要重新渲染組件的時(shí)候份乒,會(huì)通過 diff 尋找到要變更的 DOM 節(jié)點(diǎn)嘱函,再把這個(gè)修改更新到瀏覽器實(shí)際的 DOM 節(jié)點(diǎn)上板惑,所以實(shí)際上不是真的渲染整個(gè) DOM 樹摘刑。這個(gè) Virtual DOM 是一個(gè)純粹的 JS 數(shù)據(jù)結(jié)構(gòu),所以性能會(huì)比原生 DOM 快很多廓奕。
Data Flow
單向數(shù)據(jù)綁定搀擂,Data Flow 只是一種應(yīng)用架構(gòu)的方式珊膜,比如數(shù)據(jù)如何存放灵奖,如何更改數(shù)據(jù)嚼沿,如何通知數(shù)據(jù)更改等等
兩種實(shí)踐:官方的 Flux 和 優(yōu)雅的 Redux
Redux 的基礎(chǔ)概念
1、整個(gè)應(yīng)用只有唯一一個(gè)可信數(shù)據(jù)源瓷患,也就是只有一個(gè) Store
2骡尽、State 只能通過觸發(fā) Action 來更改
3、State 的更改必須寫成純函數(shù)尉尾,也就是每次更改總是返回一個(gè)新的 State爆阶,在 Redux 里這種函數(shù)稱為 Reducer
Action 很簡單燥透,就是一個(gè)單純的包含 { type, payload } 的對象沙咏,type 是一個(gè)常量用來標(biāo)示動(dòng)作類型,payload 是這個(gè)動(dòng)作攜帶的數(shù)據(jù)班套。
action = {
type: 'ADD_TODO',
text: 'Build my first Redux app'
}
Action Creators 是一個(gè)pure function肢藐,它最后會(huì)返回一個(gè) action 對象
function addTodo(text) {
return {
type: 'ADD_TODO',
text
}
}
Reducer 用來處理 Action 觸發(fā)的對狀態(tài)樹的更改,接受 oldState 和 action 兩個(gè)參數(shù)吱韭,返回一個(gè)新的 newState
state:(oldState, action) => newState
const initialState = {
a: 'a',
b: 'b'
};
function someApp(state = initialState, action) {
switch (action.type) {
case 'CHANGE_A':
return { ...state, a: 'Modified a' };
case 'CHANGE_B':
return { ...state, b: action.payload };
default:
return state
}
}
Redux 里面只有一個(gè) Store吆豹,對應(yīng)一個(gè) State 狀態(tài),所以整個(gè) State 對象就是由一個(gè) reducer 函數(shù)管理理盆,但是如果所有的狀態(tài)更改邏輯都放在這一個(gè) reducer 里面痘煤,顯然會(huì)變得越來越巨大,越來越難以維護(hù)猿规。得益于純函數(shù)的實(shí)現(xiàn)衷快,我們只需要稍微變通一下,讓狀態(tài)樹上的每個(gè)字段都有一個(gè) reducer 函數(shù)來管理就可以拆分成很小的 reducer 了
Redux 提供了一個(gè)工具函數(shù) combineReducers 來簡化這種 reducer 合并
import { combineReducers } from 'redux';
const someApp = combineReducers({
a: reducerA,
b: reducerB
});
將 root reducer 函數(shù)傳遞給 createStore 方法即可
import { createStore } from 'redux';
import someApp from './reducers';
let store = createStore(someApp);
其實(shí)就構(gòu)成了一個(gè)“單向數(shù)據(jù)流”
store.dispatch(action) -> reducer(state, action) -> store.getState()
Provider作為一個(gè)容器組件姨俩,用來接受 Store蘸拔,并且讓 Store 對子組件可用
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import App from './app';
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Connect 這個(gè)方法調(diào)用會(huì)返回另一個(gè)函數(shù)师郑,這個(gè)返回的函數(shù)來接受一個(gè)組件類作為參數(shù),最后才返回一個(gè)和 Redux store 關(guān)聯(lián)起來的新組件
connect([mapStateToProps], mapDispatchToProps], [mergeProps], [options])
第一個(gè)可選參數(shù)是一個(gè)函數(shù)调窍,只有指定了這個(gè)參數(shù)宝冕,這個(gè)關(guān)聯(lián)(connected)組件才會(huì)監(jiān)聽 Redux Store 的更新,每次更新都會(huì)調(diào)用mapStateToProps 這個(gè)函數(shù)邓萨,返回一個(gè)字面量對象將會(huì)合并到組件的 props 屬性地梨。
第二個(gè)可選參數(shù)是一個(gè)函數(shù),用來指定如何傳遞dispatch 給組件缔恳,在這個(gè)函數(shù)里面直接 dispatch action creator湿刽,返回一個(gè)字面量對象將會(huì)合并到組件的 props 屬性,這樣關(guān)聯(lián)組件可以直接通過 props 調(diào)用到 action
import React, { Component } from 'react';
import someActionCreator from './actions/someAction';
import * as actionCreators from './actions/otherAction';
function mapStateToProps(state) {
return {
propName: state.propName
};
}
function mapDispatchProps(dispatch) {
return {
someAction: (arg) => dispatch(someActionCreator(arg)),
otherActions: bindActionCreators(actionCreators, dispatch)
};
}
class App extends Component {
render() {
// `mapStateToProps` 和 `mapDispatchProps` 返回的字段都是 `props`
const { propName, someAction, otherActions } = this.props;
return (
<div onClick={someAction.bind(this, 'arg')}>
{propName}
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchProps)(App);
react的核心
轉(zhuǎn)換Transformation
UIs 只是把數(shù)據(jù)通過映射關(guān)系轉(zhuǎn)換成另一種形式的數(shù)據(jù)
The same input gives the same output
抽象Abstraction
You can't fit a complex UI in a single function though. It is important that UIs can be abstracted into reusable pieces that don't leak their implementation details. Such as calling one function from another.
不可以用單個(gè)函數(shù)就實(shí)現(xiàn)復(fù)雜的UI褐耳,把 UI 抽象成多個(gè)隱藏內(nèi)部細(xì)節(jié)诈闺,又可復(fù)用的函數(shù)。通過在一個(gè)函數(shù)中調(diào)用另一個(gè)函數(shù)來實(shí)現(xiàn)铃芦。
組合Composition
build abstractions from the containers that compose other abstractions
combine two or more different abstractions into a new one
將兩個(gè)或者多個(gè)不同的抽象組合到新的抽象
react項(xiàng)目構(gòu)建
react技術(shù)棧
react
webpack
react-router
redux
redux-thunk (this API requires redux@>=3.1.0)
es6
react-redux-boilerplate