成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

React-redux進(jìn)階之Immutable.js

孫淑建 / 349人閱讀

摘要:的優(yōu)勢(shì)保證不可變每次通過(guò)操作的對(duì)象都會(huì)返回一個(gè)新的對(duì)象豐富的性能好通過(guò)字典樹(shù)對(duì)數(shù)據(jù)結(jié)構(gòu)的共享的問(wèn)題與原生交互不友好通過(guò)生成的對(duì)象在操作上與原生不同,如訪問(wèn)屬性,。

Immutable.js

Immutable的優(yōu)勢(shì)

1. 保證不可變(每次通過(guò)Immutable.js操作的對(duì)象都會(huì)返回一個(gè)新的對(duì)象)  
2. 豐富的API  
3. 性能好 (通過(guò)字典樹(shù)對(duì)數(shù)據(jù)結(jié)構(gòu)的共享)



Immutable的問(wèn)題

1. 與原生JS交互不友好 (通過(guò)Immutable生成的對(duì)象在操作上與原生JS不同,如訪問(wèn)屬性,myObj.prop1.prop2.prop3 => myImmutableMap.getIn([‘prop1’, ‘prop2’, ‘prop3’])。另外其他的第三方庫(kù)可能需要的是一個(gè)普通的對(duì)象)  
2. Immutable的依賴性極強(qiáng) (一旦在代碼中引入使用,很容易傳播整個(gè)代碼庫(kù),并且很難在將來(lái)的版本中移除)  
3. 不能使用解構(gòu)和對(duì)象運(yùn)算符 (相對(duì)來(lái)說(shuō),代碼的可讀性差)  
4. 不適合經(jīng)常修改的簡(jiǎn)單對(duì)象 (Immutable的性能比原生慢,如果對(duì)象簡(jiǎn)單,并且經(jīng)常修改,不適合用)  
5. 難以調(diào)試 (可以采用 Immutable.js Object Formatter擴(kuò)展程序協(xié)助)  
6. 破壞JS原生對(duì)象的引用,造成性能低下 (toJs每次都會(huì)返回一個(gè)新對(duì)象)


原生Js遇到的問(wèn)題

原生Js遇到的問(wèn)題

// 場(chǎng)景一
var obj = {a:1, b:{c:2}};
func(obj);
console.log(obj)  //輸出什么??

// 場(chǎng)景二
var obj = ={a:1};
var obj2 = obj;
obj2.a = 2;
console.log(obj.a);  // 2
console.log(obj2.a);  // 2

代碼來(lái)源:https://juejin.im/post/5948985ea0bb9f006bed7472
// ajax1
this.props.a = {
  data: 1,
}
// ajax2
nextProps.a = {
  data: 1,
}
//shouldComponentUpdate()
shallowEqual(this.props, nextProps) // false
// 數(shù)據(jù)相同但是因?yàn)橐貌煌斐刹槐匾膔e-rederning
由于Js中的對(duì)象是引用類型的,所以很多時(shí)候我們并不知道我們的對(duì)象在哪里被操作了什么,而在Redux中,因?yàn)镽educer是一個(gè)純函數(shù),每次返回的都是一個(gè)新的對(duì)象(重新生成對(duì)象占用時(shí)間及內(nèi)存),再加上我們使用了connect這個(gè)高階組件,官方文檔中雖然說(shuō)react-redux做了一些性能優(yōu)化,但終究起來(lái),react-redux只是對(duì)傳入的參數(shù)進(jìn)行了一個(gè)淺比較來(lái)進(jìn)行re-redering(為什么不能在mapStateToProps中使用toJs的原因)。再進(jìn)一步,假如我們的state中的屬性嵌套了好幾層(隨著業(yè)務(wù)的發(fā)展),對(duì)于原來(lái)想要的數(shù)據(jù)追蹤等都變得極為困難,更為重要的是,在這種情況下,我們一些沒(méi)有必要的組件很可能重復(fù)渲染了多次。  


總結(jié)起來(lái)就是以下幾點(diǎn)(問(wèn)題雖少,但都是比較嚴(yán)重的):

1. 無(wú)法追蹤Js對(duì)象  
2. 項(xiàng)目復(fù)雜時(shí),reducer生成新對(duì)象性能低  
3. 只做淺比較,有可能會(huì)造成re-redering不符合預(yù)期(多次渲染或不更新)


為什么不使用深比較

或許有人會(huì)疑惑,為什么不使用深比較來(lái)解決re-redering的問(wèn)題,答案很簡(jiǎn)單,因?yàn)橄姆浅>薮髜  
想象一下,如果你的參數(shù)復(fù)雜且巨大, 對(duì)每一個(gè)進(jìn)行比較是多么消耗時(shí)間的一件事~  


使用Immutable解決問(wèn)題

項(xiàng)目復(fù)雜后, 追蹤困難

使用Immutable之后,這個(gè)問(wèn)題自然而然就解決了。所謂的追蹤困難,無(wú)非就是因?yàn)閷?duì)象是mutable的,我們無(wú)法確定它到底何時(shí)何處被改變,而Immutable每次都會(huì)保留原來(lái)的對(duì)象,重新生成一個(gè)對(duì)象,(與redux的純函數(shù)概念一樣)。但也要注意寫(xiě)代碼時(shí)的習(xí)慣:

// javascript
const obj = { a: 1 }
function (obj) {
  obj.b = 2
  ...
}

// Immutable
const obj = Map({ a : 1 })
function (obj) {
  const obj2 = obj.set({ "b", 2 })
}


reducer生成新對(duì)象性能差
當(dāng)項(xiàng)目變得復(fù)雜時(shí),每一次action對(duì)于生成的新state都會(huì)消耗一定的性能,而Immutable.js在這方面的優(yōu)化就很好?;蛟S你會(huì)疑惑為什么生成對(duì)象還能優(yōu)化?請(qǐng)往下看~

在前面就講到,Immutable是通過(guò)字典樹(shù)來(lái)做==結(jié)構(gòu)共享==的


(圖片來(lái)自網(wǎng)絡(luò))

這張圖的意思就是

immutable使用先進(jìn)的tries(字典樹(shù))技術(shù)實(shí)現(xiàn)結(jié)構(gòu)共享來(lái)解決性能問(wèn)題,當(dāng)我們對(duì)一個(gè)Immutable對(duì)象進(jìn)行操作的時(shí)候,ImmutableJS會(huì)只clone該節(jié)點(diǎn)以及它的祖先節(jié)點(diǎn),其他保持不變,這樣可以共享相同的部分,大大提高性能。


re-rendering不符合預(yù)期

其實(shí)解決這個(gè)問(wèn)題是我們用Immutable的主要目的,先從淺比較說(shuō)起
淺比較引起的問(wèn)題在這之前已經(jīng)講過(guò),事實(shí)上,即使Immutable之后,connect所做的依然是淺比較,但因?yàn)镮mmutable每次生成的對(duì)象引用都不同,哪怕是修改的是很深層的東西,最后比較的結(jié)果也是不同的,所以在這里解決了第一個(gè)問(wèn)題,==re-rendering可能不會(huì)出現(xiàn)==。
但是, 我們還有第二個(gè)問(wèn)題, ==沒(méi)必要的re-rendering==,想要解決這個(gè)問(wèn)題,則需要我們?cè)俜庋b一個(gè)高階組件,在這之前需要了解下Immutable的 is API

// is()   判斷兩個(gè)immutable對(duì)象是否相等
immutable.is(imA, imB);

這個(gè)API有什么不同, ==這個(gè)API比較的是值,而不是引用==,So: 只要兩個(gè)值是一樣的,那么結(jié)果就是true

const a = Immutable.fromJS({
  a: {
    data: 1,
  },
  b: {
    newData: {
      data: 1
    }
  }
})
const target1 = a.get("a")
const target2 = a.getIn(["b", "newData"])
console.log(Immutable.is(target1, target2)) //is比較的依據(jù)就是每個(gè)值的hashcode
// 這個(gè)hashcode就相當(dāng)于每個(gè)值的一個(gè)ID,不同的值肯定有不同的ID,相同的ID對(duì)應(yīng)著的就是相同的值。

也就是說(shuō),對(duì)于下面的這種情況, 我們可以不用渲染

// ajax1
this.props.a = {
  data: 1,
}
// ajax2
nextProps.a = {
  data: 1,
}
//shouldComponentUpdate()
Immutable.is(this.props, nextProps) // true

最后, 我們需要封裝一個(gè)高階組件來(lái)幫助我們統(tǒng)一處理是否需要re-rendering的情況

//baseComponent.js   component的基類方法

import React from "react";
import {is} from "immutable";

class BaseComponent extends React.Component {
    constructor(props, context, updater) {
        super(props, context, updater);
    }

    shouldComponentUpdate(nextProps, nextState) {
        const thisProps = this.props || {};
        const thisState = this.state || {};
        nextState = nextState || {};
        nextProps = nextProps || {};

        if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
            Object.keys(thisState).length !== Object.keys(nextState).length) {
            return true;
        }

        for (const key in nextProps) {
            if (!is(thisProps[key], nextProps[key])) {
                return true;
            }
        }

        for (const key in nextState) {
            if (!is(thisState[key], nextState[key])) {
                return true;
            }
        }
        return false;
    }
}

export default BaseComponent;

代碼來(lái)源鏈接:https://juejin.im/post/5948985ea0bb9f006bed7472


使用Immutable需要注意的點(diǎn)

使用Immutable需要注意的點(diǎn)

1. 不要混合普通的JS對(duì)象和Immutable對(duì)象 (不要把Imuutable對(duì)象作為Js對(duì)象的屬性,或者反過(guò)來(lái))  
2. 對(duì)整顆Reudx的state樹(shù)作為Immutable對(duì)象  
3. 除了展示組件以外,其他地方都應(yīng)該使用Immutable對(duì)象 (提高效率,而展示組件是純組件,不應(yīng)該使用) 
4. 少用toJS方法 (一個(gè)是因?yàn)榉穸薎mmutable,另外則是操作非常昂貴)  
5. 你的Selector應(yīng)該永遠(yuǎn)返回Immutable對(duì)象 (即mapStateToProps,因?yàn)閞eact-redux中是通過(guò)淺比較來(lái)決定是否re-redering,而使用toJs的話,每次都會(huì)返回一個(gè)新對(duì)象,即引用不同)


通過(guò)高階組件,將Immutable對(duì)象轉(zhuǎn)為普通對(duì)象傳給展示組件

1. 高階組件返回一個(gè)新的組件,該組件接受Immutable參數(shù),并在內(nèi)部轉(zhuǎn)為普通的JS對(duì)象  
2. 轉(zhuǎn)為普通對(duì)象后, 新組件返回一個(gè)入?yún)槠胀▽?duì)象的展示組件
import React from "react"
import { Iterable } from "immutable"

export const toJS = WrappedComponent => wrappedComponentProps => {
  const KEY = 0
  const VALUE = 1

  const propsJS = Object.entries(wrappedComponentProps).reduce(
    (newProps, wrappedComponentProp) => {
      newProps[wrappedComponentProp[KEY]] = Iterable.isIterable(
        wrappedComponentProp[VALUE]
      )
        ? wrappedComponentProp[VALUE].toJS()
        : wrappedComponentProp[VALUE]
      return newProps
    },
    {}
  )

  return 
}
import { connect } from "react-redux"

import { toJS } from "./to-js"
import DumbComponent from "./dumb.component"

const mapStateToProps = state => {
  return {
    // obj is an Immutable object in Smart Component, but it’s converted to a plain
    // JavaScript object by toJS, and so passed to DumbComponent as a pure JavaScript
    // object. Because it’s still an Immutable.JS object here in mapStateToProps, though,
    // there is no issue with errant re-renderings.
    obj: getImmutableObjectFromStateTree(state)
  }
}
export default connect(mapStateToProps)(toJS(DumbComponent))
參考


Immutable.js 以及在 react+redux 項(xiàng)目中的實(shí)踐

Using Immutable.JS with Redux

不變應(yīng)萬(wàn)變-Immutable優(yōu)化React

React-Redux分析

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/101588.html

相關(guān)文章

  • React-Redux進(jìn)階(像VUEX一樣使用Redux)

    摘要:前言是一個(gè)非常實(shí)用的狀態(tài)管理庫(kù),對(duì)于大多數(shù)使用庫(kù)的開(kāi)發(fā)者來(lái)說(shuō),都是會(huì)接觸到的。在使用享受其帶來(lái)的便利的同時(shí),我們也深受其問(wèn)題的困擾。只支持同步,讓狀態(tài)可預(yù)測(cè),方便測(cè)試。粗暴地級(jí)聯(lián)式刷新視圖使用優(yōu)化。 前言 Redux是一個(gè)非常實(shí)用的狀態(tài)管理庫(kù),對(duì)于大多數(shù)使用React庫(kù)的開(kāi)發(fā)者來(lái)說(shuō),Redux都是會(huì)接觸到的。在使用Redux享受其帶來(lái)的便利的同時(shí), 我們也深受其問(wèn)題的困擾。 redux...

    levius 評(píng)論0 收藏0
  • 一個(gè)基于React整套技術(shù)棧+Node.js的前端頁(yè)面制作工具

    摘要:是一個(gè)前端頁(yè)面制作工具,方便產(chǎn)品,運(yùn)營(yíng)和視覺(jué)的同學(xué)迅速開(kāi)發(fā)簡(jiǎn)單的前端頁(yè)面,從而可以解放前端同學(xué)的工作量。支持恢復(fù)現(xiàn)場(chǎng)功能關(guān)閉頁(yè)面配置不丟失支持操作。提供了一個(gè)方法,用于的拆分。就是發(fā)出的通知,表示應(yīng)該要發(fā)生變化了。 pagemaker是一個(gè)前端頁(yè)面制作工具,方便產(chǎn)品,運(yùn)營(yíng)和視覺(jué)的同學(xué)迅速開(kāi)發(fā)簡(jiǎn)單的前端頁(yè)面,從而可以解放前端同學(xué)的工作量。此項(xiàng)目創(chuàng)意來(lái)自網(wǎng)易樂(lè)得內(nèi)部項(xiàng)目nfop中的page...

    ermaoL 評(píng)論0 收藏0
  • 2017-06-23 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選大前端公共知識(shí)梳理這些知識(shí)你都掌握了嗎以及在項(xiàng)目中的實(shí)踐深入貫徹閉包思想,全面理解閉包形成過(guò)程重溫核心概念和基本用法前端學(xué)習(xí)筆記自定義元素教程阮一峰的網(wǎng)絡(luò)日志中文譯回調(diào)是什么鬼掘金譯年,一個(gè)開(kāi)發(fā)者的好習(xí)慣知乎專 2017-06-23 前端日?qǐng)?bào) 精選 大前端公共知識(shí)梳理:這些知識(shí)你都掌握了嗎?Immutable.js 以及在 react+redux 項(xiàng)目中的實(shí)踐深入貫徹閉包思...

    Vixb 評(píng)論0 收藏0
  • redux常見(jiàn)問(wèn)題答疑

    摘要:為什么使用的核心是將組件化,由數(shù)據(jù)驅(qū)動(dòng)的展現(xiàn)。僅僅使用進(jìn)行開(kāi)發(fā)的痛點(diǎn)組件嵌套層級(jí)深,回調(diào)地獄。遵守容器組件與展示組件分離的原則。 為什么使用redux React的核心是將UI組件化,由數(shù)據(jù)驅(qū)動(dòng)UI的展現(xiàn)。但是如何管理數(shù)據(jù)模型、組件與數(shù)據(jù)模型之間的通信,react并沒(méi)有很好的解決方案。Redux由flux演變而來(lái),同時(shí)簡(jiǎn)化了Flux的流程。 僅僅使用react進(jìn)行開(kāi)發(fā)的痛點(diǎn) 組件嵌套...

    wing324 評(píng)論0 收藏0
  • 前端進(jìn)階(11) - js 數(shù)據(jù)結(jié)構(gòu)類型擴(kuò)展:immutable-js

    摘要:數(shù)據(jù)結(jié)構(gòu)類型擴(kuò)展相對(duì)之類的強(qiáng)類型語(yǔ)言,有一點(diǎn)很大的區(qū)別就是,數(shù)據(jù)結(jié)構(gòu)只有與,并且都是動(dòng)態(tài)可變的,而有等數(shù)據(jù)結(jié)構(gòu)。所以,為了能在中也使用這些數(shù)據(jù)結(jié)構(gòu),就應(yīng)運(yùn)而生。擴(kuò)充了中的不可變集合,即一旦創(chuàng)建就不能改變的數(shù)據(jù)類型。 js 數(shù)據(jù)結(jié)構(gòu)類型擴(kuò)展:immutable-js 相對(duì) java、.net 之類的強(qiáng)類型語(yǔ)言,js 有一點(diǎn)很大的區(qū)別就是,數(shù)據(jù)結(jié)構(gòu)只有 array 與 object,并且都...

    BLUE 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<