immutable在redux中的應(yīng)用

本文轉(zhuǎn)自我的博客閱讀原文替废。

一覽

整合各個子的reducer

redux官方提供的combineReducers只支持原生JS的形式,所以這里要用redux-immutable提供的combineReducers來代替螟炫。

import {combineReducers} from 'redux-immutable'
import dish from './dish'
import menu from './menu'
import cart from './cart'
// 整合各個子的reducer
const rootReducer = combineReducers({dish, menu, cart})
export default rootReducer

reducer中的initialState肯定也需要初始化成immutable類型

// Map里面?zhèn)鞯氖且粋€原生JS對象,初始化reducer中的initialState時建議用Map方法而不是fromJS方法惭婿,效率更高
const initialState = Immutable.Map({})
export default function menu(state = initialState, action) {
  switch (action.type) {
    case SET_ERROR:
      return state.set('isError', true)
  }
}

將immutable的數(shù)據(jù)映射到組件的props中

state成為了immutable類型不恭,所以mapStateToProps也要改寫成immutable的取值方法。

function mapStateToProps(state) {
  return {
    menuList: state.getIn(['dish', 'list']), //使用get或者getIn來獲取state中的變量
    CartList: state.getIn(['dish', 'cartList'])
  }
}

immutable數(shù)據(jù)類型檢驗(yàn)

這就需要我們 import 專門針對immutable類型進(jìn)行校驗(yàn)的庫:react-immutable-proptypes财饥,使用方法基本上和普通的PropTypes一致:

propTypes: {
  oldListTypeChecker: React.PropTypes.instanceOf(Immutable.List),
  anotherWay: ImmutablePropTypes.list,
  requiredList: ImmutablePropTypes.list.isRequired,
  mapsToo: ImmutablePropTypes.map,
  evenIterable: ImmutablePropTypes.iterable
}
// 與此同時换吧,產(chǎn)生defaultProps的地方應(yīng)該為:
fromJS({
  prop1: xxx,
  prop2: xxx,
  prop3: xxx
}).toObject()

裝飾shouldComponentUpdate

減少頁面無意義渲染的次數(shù)是immutable提升react效率的重中之重。

import pureRender from "pure-render-immutable-decorator"
// @pureRender會幫你實(shí)現(xiàn)shouldComponentUpdate钥星。如果在這個鉤子中還有自己的邏輯的話沾瓦,請參看官方文檔
@pureRender
class List extends Component {
  constructor(props, context) {
    super(props, context)
  }
  render() {
    return (
      <div> </div>
    )
  }
}

上面用到decorator,在js的babel loader里面谦炒,新增plugins: [‘transform-decorators-legacy’]贯莺。
這個模塊下面還有一個不用immutable的可以對原生JS對象進(jìn)行深比較的模塊(pure-render-deepCompare-decorator)。

進(jìn)階

immutable.js使用過程中的一些注意點(diǎn)

  • fromJS和toJS會深度轉(zhuǎn)換數(shù)據(jù)宁改,隨之帶來的開銷較大缕探,盡可能避免使用,單層數(shù)據(jù)轉(zhuǎn)換使用Map()和List()
  • js是弱類型还蹲,但Map類型的key必須是string5摹(也就是我們?nèi)≈凳且胓et('1')而不是get(1))
  • 所有針對immutable變量的增刪改必須左邊有賦值,因?yàn)樗胁僮鞫疾粫淖冊瓉淼闹得蘸埃皇巧梢粋€新的變量
  • 獲取深層深套對象的值時不需要做每一層級的判空(JS中如果不判空會報錯潭兽,immutable中只會給undefined)
  • immutable對象直接可以轉(zhuǎn)JSON.stringify(),不需要顯式手動調(diào)用toJS()轉(zhuǎn)原生
  • 判斷對象是否是空可以直接用size
  • 調(diào)試過程中要看一個immutable變量中真實(shí)的值,可以chrome中加斷點(diǎn)斗遏,在console中使用.toJS()方法來查看

高階組件封裝

對于使用immutable.js的項(xiàng)目山卦,在應(yīng)用公共組件的時候,由于公共組件的內(nèi)部實(shí)現(xiàn)一定是原生JS數(shù)據(jù)诵次,所以我們只能傳遞原生JS數(shù)據(jù)到公共組件账蓉,但是如果轉(zhuǎn)換成了原生JS數(shù)據(jù),就又會出現(xiàn)"React.addons.PureRenderMixin提供的shouldComponentUpdate()是淺比較"問題逾一,對此可以使用下面的高階組件進(jìn)行封裝铸本。

/* 定義高階組件 */
import {React} from 'base'
// 通過Immutable.is 封裝過的 shouldComponentUpdate
import {shouldComponentUpdate} from '../immutable-pure-render-decorator'

export default ComposedComponent => {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.shouldComponentUpdate = shouldComponentUpdate.bind(this)
    }
    render() {
      const props = this.props.toJS ? this.props.toJS() : this.props
      return <ComposedComponent { ...this.props} { ...props} />
    }
  }
}

/* 使用高階組件 */
import highComponent from '../../../../widgets/libs/utils/highComponent'
// 公共組件
import Dialog from '@alife/dialog'
function mapStateToProps(state) {
}
function mapDispatchToProps(dispatch) {
}
// 通過高階組件封裝
export default connect(mapStateToProps, mapDispatchToProps)(highComponent(Dialog))

immutable常用API

//Map()  原生object轉(zhuǎn)Map對象 (只會轉(zhuǎn)換第一層,注意和fromJS區(qū)別)
immutable.Map({name:'danny', age:18})
//List()  原生array轉(zhuǎn)List對象 (只會轉(zhuǎn)換第一層嬉荆,注意和fromJS區(qū)別)
immutable.List([1,2,3,4,5])
//fromJS()   原生js轉(zhuǎn)immutable對象  (深度轉(zhuǎn)換归敬,會將內(nèi)部嵌套的對象和數(shù)組全部轉(zhuǎn)成immutable)
immutable.fromJS([1,2,3,4,5])    //將原生array  --> List
immutable.fromJS({name:'danny', age:18})   //將原生object  --> Map
//toJS()  immutable對象轉(zhuǎn)原生js  (深度轉(zhuǎn)換,會將內(nèi)部嵌套的Map和List全部轉(zhuǎn)換成原生js)
immutableData.toJS();
//查看List或者map大小  
immutableData.size  或者 immutableData.count()
// is()   判斷兩個immutable對象是否相等
immutable.is(imA, imB);
//merge()  對象合并
var imA = immutable.fromJS({a:1,b:2});
var imA = immutable.fromJS({c:3});
var imC = imA.merge(imB);
console.log(imC.toJS())  //{a:1,b:2,c:3}
//增刪改查(所有操作都會返回新的值,不會修改原來值)
var immutableData = immutable.fromJS({
    a:1,
    b:2汪茧,
    c:{
        d:3
    }
});
var data1 = immutableData.get('a') //  data1 = 1  
var data2 = immutableData.getIn(['c', 'd']) // data2 = 3   getIn用于深層結(jié)構(gòu)訪問
var data3 = immutableData.set('a' , 2);   // data3中的 a = 2
var data4 = immutableData.setIn(['c', 'd'], 4);   //data4中的 d = 4
var data5 = immutableData.update('a',function(x){return x+4})   //data5中的 a = 5
var data6 = immutableData.updateIn(['c', 'd'],function(x){return x+4})   //data6中的 d = 7
var data7 = immutableData.delete('a')   //data7中的 a 不存在
var data8 = immutableData.deleteIn(['c', 'd'])   //data8中的 d 不存在

參考資料

如何用React+Redux+ImmutableJS進(jìn)行SPA開發(fā)
React移動web極致優(yōu)化
immutable.js 在React椅亚、Redux中的實(shí)踐以及常用API簡介
Immutable.js 以及在 react+redux 項(xiàng)目中的實(shí)踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市舱污,隨后出現(xiàn)的幾起案子呀舔,更是在濱河造成了極大的恐慌,老刑警劉巖扩灯,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件媚赖,死亡現(xiàn)場離奇詭異,居然都是意外死亡珠插,警方通過查閱死者的電腦和手機(jī)惧磺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捻撑,“玉大人磨隘,你說我怎么就攤上這事」嘶迹” “怎么了番捂?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長江解。 經(jīng)常有香客問我设预,道長,這世上最難降的妖魔是什么犁河? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任鳖枕,我火速辦了婚禮,結(jié)果婚禮上呼股,老公的妹妹穿的比我還像新娘耕魄。我一直安慰自己画恰,他們只是感情好彭谁,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著允扇,像睡著了一般缠局。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上考润,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天狭园,我揣著相機(jī)與錄音,去河邊找鬼糊治。 笑死唱矛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播绎谦,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼管闷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了窃肠?” 一聲冷哼從身側(cè)響起包个,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冤留,沒想到半個月后碧囊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纤怒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年糯而,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泊窘。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡歧蒋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出州既,到底是詐尸還是另有隱情谜洽,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布吴叶,位于F島的核電站阐虚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蚌卤。R本人自食惡果不足惜实束,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望逊彭。 院中可真熱鬧咸灿,春花似錦、人聲如沸侮叮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽囊榜。三九已至审胸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卸勺,已是汗流浹背砂沛。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留曙求,地道東北人碍庵。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓映企,卻偏偏與公主長得像,于是被迫代替她去往敵國和親静浴。 傳聞我的和親對象是個殘疾皇子卑吭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容