react使用redux作狀態管理,實現多個組件之間的信息共享,解決了父子組件、兄弟組件之間的複雜通訊問題。vue有vuex,總之是一種flux的思想。react提供了react-redux這個庫,一看名字就知道是爲了將react和redux關聯起來,react-redux有connect高階函數以及Provider組件、milddleware、thunk等,來實現一下。vue
篇幅過長,多分了幾篇。react
這裏先不考慮中間件機制vuex
import { createStore } from 'redux' function counter(state = 10, action) { console.log(state, action) switch (action.type) { case 'add': return state + 1 case 'less': return state - 1 default: return state } } const store = createStore(counter) const init = store.getState() console.log(`Init count: ${init}`) function listener(){ const current = store.getState() console.log(`count: ${current}`) } store.subscribe(listener) store.dispatch({ type: 'add' }) store.dispatch({ type: 'less' })
這是redux簡單的例子,首先咱們定義了一個reducer叫作counter,接下來使用redux提供的createStore方法將reducer傳入,構造出了一個store,而後基於觀察者模式,觸發相應的action,進行相應的響應。redux
Redux重點的方法就是createStore、getState、subscribe、dispatch這四個方法。大致講一下思路,咱們的Redux,這裏就叫myRedux,myRedux和Redux同樣,都是隻暴露出來一個方法,那就是createStore,而後createStore保存着一個state,能夠是對象、字符串、數組等,能夠經過getState方法來訪問state,還有對state的監聽器以及訂閱的方法,實現一下。數組
export function createStore (reducer) { let state = {} let listeners = [] function getState () { return state } function subscribe (listener) { listeners.push(listener) } function dispatch (action) { state = reducer(state, action) listeners.forEach(listener => listener()) return action } // 爲了確保createStore以後,store.getState中就有state的初始值 dispatch({type: '@myRedux/qwe'}) return {getState, subscribe, dispatch} }
其實就是一個觀察者模式,值得注意的是:當執行完createStore以後,執行stroe.getState方法就能獲取到初始的狀態(咱們這裏是10),因此須要咱們的reducer先執行一次,那麼咱們就要在createStore中就先dispatch一下,代碼中有體現。Redux中也是這麼作的,Redux初始化dispatch的type值是@@redux/INIT
,能夠看一下。安全
這麼作是爲了確保初始化dispatch的type值不會和用戶定義的type值重複,咱們代碼裏type爲@myRedux/qwe
。less
要理解react-redux原理,必須先說下react中的context。父組件向子組件傳遞數據,能夠經過props,若是層級比較深呢?就很差了,會有性能問題,咱們能夠經過context來實現跨級傳遞數據。ide
context是全局的,在組件中聲明,全部的子組件均可以獲取到context,react以爲全局不是很安全,因此要求context都是強數據類型,即任何想訪問context裏面的屬性的組件都必須指定一個contextTypes
的屬性,若是沒有指定該屬性的話,用this.context
訪該屬性就會出錯。函數
一樣,經過getChildContext
方法指定傳遞給子組件的屬性也須要被指定數據類型,經過childContextTypes來指定,不指定一樣會產生錯誤。性能
下面是一個簡單例子。
import React from 'react' import PropTypes from 'prop-types' class Son extends React.Component{ render(){ return ( <div> <p>子組件</p> <GrandSon/> </div> ) } } class GrandSon extends React.Component{ static contextTypes = { user:PropTypes.string } render(){ console.log(this.context) return ( <div> <p>孫組件</p> <div>孫組件收到來自父組件的信息:{this.context.user}</div> </div> ) } } class Father extends React.Component{ static childContextTypes = { user:PropTypes.string } constructor(props){ super(props) this.state = {user:'user12'} } getChildContext(){ return this.state } render(){ return ( <div> <p>父組件,要給孫組件:{this.state.user}</p> <Son/> </div> ) } } export default Father
在這裏就不須要經過props一層一層的往下傳遞屬性了,這就是context。
那麼context和咱們的react-redux有什麼關係呢,用過的都知道,Provider組件在整個應用組件上包了一層,讓整個應用組件成爲Provider的子組件,看到這裏,你是否是有點懂了,跟上面的例子很像嘛,對的,就是這樣,咱們的Provider組件接收Redux的store做爲props,經過context對象傳遞給子組件。
咱們下一篇就會說道Provider組件。