摘要:深復制與淺復制淺復制同樣的方式深復制因為存儲對象都是存地址的,所以淺復制會導致和指向同一塊內存地址,大概的示意圖如下。
深復制與淺復制
let obj = { a: 1, arr: [1, 2] }; let obj1 = obj; //淺復制 obj1.a = 2 console.log(obj) // { a:2, arr: [1,2] }; //同樣的方式 let obj = { a: 1, arr: [1, 2] }; let obj2 = deepCopy(obj); //深復制 obj2.a = 2 console.log(obj) // { a:1, arr: [1,2] };
es6-Object.assign()方法因為JavaScript存儲對象都是存地址的,所以淺復制會導致 obj 和 obj1
指向同一塊內存地址,大概的示意圖如下。而深復制一般都是開辟一塊新的內存地址,將原對象的各個屬性逐個復制出去。
深復制只有一層,之后為淺復制(除非再次使用Object.assign嵌套方式賦值)
let obj = { a: 1, arr: [1, 2] }; let obj1 = Object.assign({}, obj); obj1.a = 2 //不變 console.log(obj) // { a:1, arr: [1,2] }; let obj = { a: { b: 20 }, arr: [1, 2] }; let obj1 = Object.assign({}, obj); obj1.a.b = 2; //除非再次使用Object.assign嵌套方式賦值 //變化 console.log(obj) // { a:{b:2}, arr: [1,2] };為什么使用不可變(immutable)的數據? (pureRender結合immutable,見末尾)
第一種方式
//recduer.js(cart)第一種方式 case types.CART_PUT_MAIN + "_SUCCESS": //更新數據 carts = state.main.carts; // carts 選中的id數組 id = action.param.id; newState = { ...state, main:{ ...state.main, itemObj:{ ...state.main.itemObj, [id]:{ ...state.main.itemObj[id], quantity:action.param.quantity } } } }; sum = sumCommon(carts, newState.main.itemObj); newState = { ...newState, main:{ ...newState.main, ...sum } }; return newState;
讓我們來看一下對數據層的變化:
componentWillReceiveProps(nextProps){ console.log(nextProps); //next:顧名思義是接收到的next->props,輸出的是上面方法中的newState的值 console.log(this.props); //cur:是當前的props的值,因為使用的是類immutable的方式,所以數據不變; }
第二種方式
//recduer.js(cart)第一種方式 case types.CART_PUT_MAIN + "_SUCCESS": newState = Object.assign({}, state); carts = newState.main.carts; // carts 選中的id數組 id = action.param.id; //淺復制 newState.main.itemObj[id].quantity = action.param.quantity;; sum = sumCommon(carts, newState.main.itemObj); newState = Object.assign({}, newState, { main: Object.assign({}, newState.main, sum) }); return newState;
讓我們來再來看一下對數據層的變化:
componentWillReceiveProps(nextProps){ console.log(nextProps); //next:顧名思義是接收到的next->props,輸出的是上面方法中的newState的值 console.log(this.props); //cur:是當前的props的值,而這個由于淺復制,這個值被改變了 }
為了讓數據變化更加可測,我們應當使用深復制相關,讓我們自己的數據更加安全
處理方法一:es7 ... 的方式直接{...obj}賦值屬于淺復制,在修改值時{...obj,a:1}就起到了類深復制的效果
更新一個 Object ,則:
let obj = { a: 0, b: 20, } obj = {...obj, a: obj.a + 1}
而不是:
obj.a = obj.a + 1
同樣的為了避免對 Object 的 in-place editing,數組也是一樣:
let arr = [ { id: 1,a: 1} ] arr = [...arr, { id: 2,a: 2} ]
而不是:
let arr = [ { id: 1, a:1} ] arr.push({ id: 2, a,2});
以這樣的方式,無需 Immutable.js ,我們可以讓應用程序狀態是 不可變(Immutable) 的。
...注意事項及要求let obj = { a: 20, arr: [1, 2] }; let obj1 = { ...obj }; //于obj1=obj一樣 // 保持統一,盡量不要使用這樣的替換(有可能造成不必要的麻煩) obj1.a = 2 //...盡量使用這樣的賦值形式 obj1 = { ...obj1 , a:2 } //深復制 console.log(obj) // { a:20, arr: [1,2] }; console.log(obj1) // { a:2, arr: [1,2] };
...與Object.assign屬于一個道理(這里和層級相關)
//你可以將其轉化為 let obj = { a: { b: 20 }, arr: [1, 2] }; let obj1 = obj obj1 = Object.assign({}, obj1, { a: Object.assign({}, obj1.a,{b:2}) }); console.log(obj) //{ a:{b:20}, arr: [1,2] } console.log(obj) //{ a:{b:2}, arr: [1,2] } 所以盡量使用...代替Object.assign處理方法二:使用immutable.js
之前方式的多層嵌套
//深復制(類immutable) newState = { ...state, main:{ ...state.main, itemObj:{ ...state.main.itemObj, [id]:{ ...state.main.itemObj[id], prop:action.param.props_str, product_id:action.param.product_id, price:action.param.price } } } }; //淺復制 newState.main.itemObj[id].prop = action.param.props_str; //immutable.js方式 ...參考immutable的api吧,暫時就不提供了--!PureRenderMixin使用請參考以下內容
簡單的說就是數據變化,比較前后兩次的數據是否相同,判斷是否重新render;否則你的父容器一改變數據,所有的子組件都重新渲染了,為了增加性能請使用pureRender;
Immutable.js及在React中的應用
Immutable 詳解及 React 中實踐
Immutable as React state
(封裝好的PureRender如下:)
"use strict"; import { is } from "immutable"; let hasOwnProperty = Object.prototype.hasOwnProperty; function shallowEqual(objA, objB) { if (objA === objB || is(objA, objB)) { return true; } if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) { return false; } let keysA = Object.keys(objA); let keysB = Object.keys(objB); if (keysA.length !== keysB.length) { return false; } let bHasOwnProperty = hasOwnProperty.bind(objB); for (let i = 0; i < keysA.length; i++) { if (!bHasOwnProperty(keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { return false; } } return true; } function shallowCompare(instance, nextProps, nextState) { return !shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState); } function shouldComponentUpdate(nextProps, nextState) { return shallowCompare(this, nextProps, nextState); } function pureRenderDecorator(component) { component.prototype.shouldComponentUpdate = shouldComponentUpdate; } module.exports = pureRenderDecorator; /*使用方式*/ import pureRender from "pure-render-decorator"; //babel配置中引入一個transform-decorators-legacy插件 @pureRender class XXX extends React.Component { //... }
PureRender的使用要求:對于子組件需要什么參數傳遞什么,不要把一大塊無用的數據引入,否則兩次傳入的this.props可能始終會不一樣,導致PureRender無效
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87883.html
摘要:原文地址什么是是指一旦被創建就不可以被改變的數據,通過使用不可變數據可以讓我們很方便的去處理數據的狀態變化檢測等問題,而且讓我們的程序變得更加的可預見怎么用大體使用深度轉換和為和淺轉換給倒數第一個賦值更多可以查看這里為什么要用其實從上面 原文地址:https://gmiam.com/post/react-... 什么是 Immutable Data ? Immutable Data 是...
摘要:四是在年出的持久性數據結構的庫,持久性指的是數據一旦創建,就不能再被更改,任何修改或添加刪除操作都會返回一個新的對象。避免大量使用操作,這樣會浪費性能。盡量將設計成扁平狀的。 一、痛點 在我們的印象中,React 好像就意味著組件化、高性能,我們永遠只需要關心數據整體,兩次數據之間的 UI 如何變化,則完全交給 React Virtual Dom 的 Diff 算法 去做。以至于我們很...
摘要:所以,深拷貝是對對象以及對象的所有子對象進行拷貝實現方式就是遞歸調用淺拷貝對于深拷貝的對象,改變源對象不會對得到的對象有影響。 上一篇 JavaScript中的繼承 前言 文章開始之前,讓我們先思考一下這幾個問題: 為什么會有淺拷貝與深拷貝 什么是淺拷貝與深拷貝 如何實現淺拷貝與深拷貝 好了,問題出來了,那么下面就讓我們帶著這幾個問題去探究一下吧! 如果文章中有出現紕漏、錯誤之處...
摘要:插件允許我們在的語法中使用在傳遞數據時,可以通過進一步提升組件的渲染性能,是針對可變對象和不可變對象所做的折衷。使用之后,僅僅改變狀態了的組件及其父組件被重新渲染。 1 前言 網頁性能最大的限制因素是瀏覽器重繪(reflow)和重排版(repaint),React的虛擬DOM就是為了盡可能減少瀏覽器的重繪和重排版,從React的渲染過程看,避免不必要的渲染可以進一步提高性能。 2 Pu...
摘要:所以,深拷貝是對對象以及對象的所有子對象進行拷貝實現方式就是遞歸調用淺拷貝對于深拷貝的對象,改變源對象不會對得到的對象有影響。 為什么會有淺拷貝與深拷貝什么是淺拷貝與深拷貝如何實現淺拷貝與深拷貝好了,問題出來了,那么下面就讓我們帶著這幾個問題去探究一下吧! 如果文章中有出現紕漏、錯誤之處,還請看到的小伙伴多多指教,先行謝過 以下↓ 數據類型在開始了解 淺拷貝 與 深拷貝 之前,讓我們先...
閱讀 2089·2021-11-23 09:51
閱讀 3697·2021-10-20 13:49
閱讀 1706·2021-09-06 15:13
閱讀 1816·2021-09-06 15:02
閱讀 3154·2021-09-02 15:11
閱讀 890·2019-08-29 15:37
閱讀 1732·2019-08-29 13:24
閱讀 2274·2019-08-29 11:28