摘要:張偉輸出結(jié)果這樣就實(shí)現(xiàn)了在源數(shù)據(jù)的基礎(chǔ)上更改了值并且輸出一個(gè)與之地址完全不同數(shù)組。
本來(lái)想將有關(guān)于immutability-helper的博文放在一起學(xué)React系列博文中,但是考慮到該插件不僅僅在React中實(shí)用到,所以就多帶帶拿出來(lái)分兩期寫(xiě)。
發(fā)現(xiàn)問(wèn)題immutability意為不變,不變性,永恒性。至于該插件能做什么,我想它的作者對(duì)它的標(biāo)注已經(jīng)很明確了mutate a copy of data without changing the original source,意為:在不改變?cè)紒?lái)源的情況下改變數(shù)據(jù)副本。
同時(shí)在這里筆者再推薦另一個(gè)與之相似的插件,那就是Facebook出品的immutable-js (我們可以認(rèn)為immutability-helper是immutable-js的終極簡(jiǎn)化版)。臉書(shū)對(duì)immutable-js的標(biāo)注也很明確:Immutable persistent data collections for Javascript which increase efficiency and simplicity,意為:使得Javascript中的持久數(shù)據(jù)集合保持不可變,從而提高效率和簡(jiǎn)單性。
仔細(xì)閱讀他們對(duì)兩個(gè)插件格子的描述,我們能得到一個(gè)關(guān)鍵字,那就是不可變。為什么要不可變?在這里筆者覺(jué)得從React角度來(lái)解釋可能會(huì)更加清晰。我們都知道React組件本身會(huì)包含N個(gè)狀態(tài),而且這些狀態(tài)會(huì)通過(guò)setState方法去更新,也就是說(shuō)React組件的狀態(tài)是可變的,實(shí)際上本就是這么一回事。但是作為React的初學(xué)者可能會(huì)誤解狀態(tài)是可變的這句話。怎么說(shuō)?因?yàn)閷?duì)于React組件而言,狀態(tài)的變化是State的變化而不是State值的變化,什么?看不懂?那我們繼續(xù)往下說(shuō)。假如我們初始化了這樣一個(gè)狀態(tài):
this.state={ name:"xiaoming", hobbies:["qq","wx"] }
現(xiàn)在才是解釋什么叫State的變化而不是State值的變化。假如我們先這樣做:
this.setState({ name:"hanmeimei" })
經(jīng)過(guò)這個(gè)操作以后,name對(duì)應(yīng)的DOM節(jié)點(diǎn)會(huì)得到更新,而如果我們這樣做:
function changeHobby() { let hobbies = this.state.hobbies; hobbies.push("Coding"); this.setState({ hobbies: hobbies }) }引出問(wèn)題
運(yùn)行了這個(gè)方法以后會(huì)發(fā)生什么?Nothing Happened, But why?
這個(gè)問(wèn)題也是經(jīng)常發(fā)生在React初學(xué)者身上,因?yàn)镽eact在檢測(cè)狀態(tài)變化時(shí)候是一個(gè)淺檢測(cè),換句話說(shuō)就是只關(guān)注name或者h(yuǎn)obbies這兩個(gè)key對(duì)應(yīng)的value有沒(méi)有變化,有變化就重新Render否則不做任何動(dòng)作。那如何去檢測(cè)value有沒(méi)有變化,其實(shí)就是根據(jù)變量的地址。我們都知道變量在內(nèi)存中都有唯一的地址。拿剛剛的兩個(gè)例子來(lái)說(shuō),為什么更新了name和更新了hobbies這兩個(gè)狀態(tài)會(huì)有兩個(gè)不同的結(jié)果?那是因?yàn)樵贘avaScritp中,string就是被設(shè)計(jì)成不可變,而數(shù)組則可變。換句話說(shuō)我們無(wú)法在保證字符串內(nèi)存地址不變的情況下改變字符串但卻可以保證數(shù)組在內(nèi)存地址不變的情況下增加或者刪除其中的某一個(gè)元素。所以這就是為什么我們更新hobbies這個(gè)狀態(tài)的情況組件并沒(méi)有刷新的原因,我們用例子來(lái)證明下數(shù)組這一特性:
let hobbies = ["qq", "wx"]; let hobbies_2 = hobbies; hobbies_2.push("Coding"); console.log(hobbies === hobbies_2);
可以看出這兩個(gè)變量實(shí)際上是同一個(gè)。
再舉個(gè)例子并且是在日常開(kāi)發(fā)中肯定會(huì)遇到過(guò)的。假如現(xiàn)在要將后臺(tái)的傳來(lái)的數(shù)據(jù)渲染成一個(gè)列表,數(shù)據(jù)如下:
[ {"id":0,name:"xiaoming"}, {"id":1,name:"lilei"}, {"id":2,name:"hanmeimei"}, ]
這是一個(gè)很簡(jiǎn)單的操作。然后我們做了一個(gè)更新的功能,當(dāng)我們將id為1的那條的姓名改成"Miss Li",那該怎么辦才能保證在setState后讓該列表組件重新渲染?估計(jì)大家心里立刻有兩個(gè)方案,一個(gè)是重新獲取后臺(tái)數(shù)據(jù)然后重新渲染,另一個(gè)是重新拷貝一份數(shù)據(jù)然后更改相應(yīng)的地方后重新set給某個(gè)State完成重新渲染。但是我們可以看出,這兩個(gè)操作最終的效果仍然是創(chuàng)建另一個(gè)與初始數(shù)組在內(nèi)容上完全相同的數(shù)組,雖然相對(duì)繁瑣但是著實(shí)有效。不過(guò)這兩個(gè)方案各有缺點(diǎn),比如第一個(gè)方案需要額外增加一次網(wǎng)絡(luò)請(qǐng)求,第二個(gè)是萬(wàn)一數(shù)據(jù)量過(guò)于龐大就會(huì)造成內(nèi)存的浪費(fèi)。
既然這樣有什么更好的解決方案呢?到這里我相信大家就明白了該篇博客的用意了,因?yàn)檫@個(gè)immutability-helper在筆者近期項(xiàng)目中使用最頻繁,所以覺(jué)得有必要拿出來(lái)說(shuō)一說(shuō)。
使用方法很簡(jiǎn)單,首先是安裝依賴
npm install immutability-helper --save
然后是在有需要的地方引入即可
import update from "immutability-helper";
這樣我們可以使用update這個(gè)方法做我們想做的事情了。
那就有人問(wèn)了,為什么它就能完美的解決問(wèn)題呢?其實(shí)很簡(jiǎn)單,就那剛剛的列表數(shù)據(jù)來(lái)說(shuō),immutability-helper會(huì)輸出一個(gè)全新的數(shù)組對(duì)象并且只會(huì)更新跟id=1有關(guān)的那條數(shù)據(jù),剩下的通過(guò)地址引用的方式引入到新數(shù)組中,這樣會(huì)最大限度的使用數(shù)據(jù)和內(nèi)存。immutability-helper工作方式
immutability-helper的工作方式也很簡(jiǎn)單,通過(guò)在update方法在使用指令就可以實(shí)現(xiàn)對(duì)數(shù)據(jù)的修改。
immutability-helper的指令組成也很簡(jiǎn)單:$+關(guān)鍵字。而且這個(gè)關(guān)鍵字我們?nèi)匀缓苁煜ぃ又驴?。它支持的指令一共有?/p>
{$push: array} push() all the items in array on the target.
{$unshift: array} unshift() all the items in array on the target.
{$splice: array of arrays} for each item in arrays call splice() on the target with the parameters provided by the item. Note: The items in the array are applied sequentially, so the order matters. The indices of the target may change during the operation.
{$set: any} replace the target entirely.
{$toggle: array of strings} toggles a list of boolean fields from the target object.
{$unset: array of strings} remove the list of keys in array from the target object.
{$merge: object} merge the keys of object with the target.
{$apply: function} passes in the current value to the function and updates it with the new returned value.
{$add: array of objects} add a value to a Map or Set. When adding to a Set you pass in an array of objects to add, when adding to a Map, you pass in [key, value] arrays like so: update(myMap, {$add: [["foo", "bar"], ["baz", "boo"]]})
{$remove: array of strings} remove the list of keys in array from a Map or Set.
這些指令關(guān)鍵字是不是很熟悉?因?yàn)槲覀冊(cè)谌粘i_(kāi)發(fā)中經(jīng)常使用到這些。下面就開(kāi)始一個(gè)一個(gè)介紹。
指令使用 $pushpush,顧名思義和數(shù)組有關(guān),其實(shí)就是向源數(shù)組中增加一個(gè)元素并且輸出一個(gè)內(nèi)容想通了的新數(shù)組??蠢樱?/p>
var update = require("immutability-helper"); const state1 = ["x"]; const state2 = update(state1, { $push: ["y"] }); // ["x", "y"] console.log(state1, state2); console.log(`state1===state2: ${state1===state2}`);
輸出結(jié)果:
同時(shí)也來(lái)熟悉下update方法的使用:update方法接受兩個(gè)參數(shù),第一個(gè)是源數(shù)據(jù),這個(gè)很好理解;第二個(gè)是操作線(筆者YY出來(lái)的),用來(lái)描述我們?nèi)绾稳ゲ僮髟磾?shù)據(jù),key是指令,value是指令所需要的數(shù)據(jù)。$unshift
unshift的作用就是向源數(shù)組的開(kāi)頭批量添加元素
var update = require("immutability-helper"); const state1 = ["x"]; const state2 = update(state1, { $unshift: ["y","Z"] }); console.log(state1, state2);
輸出結(jié)果:
$splicesplice的作用就是向源數(shù)組中添加/刪除元素。參數(shù)接受多個(gè)數(shù)組,每個(gè)數(shù)組為一組操作。每一組與實(shí)際splice方法的參數(shù)相同。
var update = require("immutability-helper"); const state1 = [0, 1, 2, 4]; const state2 = update(state1, { $splice: [ [3, 1, 3, 4, 5, 6, 7] ] }); console.log(state1, state2);
輸出結(jié)果:
set指令被用來(lái)改成字面量對(duì)象中的某個(gè)key的值。
var update = require("immutability-helper"); const data = { "id": 0, name: "xiaoming" }; const data2 = update(data, { name: { $set: "Miss Li" } }); console.log(data, data2);
輸出結(jié)果:
$toggletoggle意為切換,該方法是用來(lái)對(duì)Boolean對(duì)象進(jìn)行切換,比如True切換為False
var update = require("immutability-helper"); const data = [true, false]; const data2 = update(data, { $toggle: [0] }); console.log(data, data2);
輸出結(jié)果:
使用方法如上,針對(duì)數(shù)組中的第1個(gè)Boolean值做切換處理。
本篇先介紹這5個(gè)指令方法。剩下的5個(gè)我們下一篇繼續(xù)。
接下來(lái)我們嘗試從上面這5個(gè)指令中找出相應(yīng)指令去解決我們前面提到的表格數(shù)據(jù)的問(wèn)題:
首先是表格的數(shù)據(jù):
[ {"id":0,name:"xiaoming"}, {"id":1,name:"lilei"}, {"id":2,name:"hanmeimei"}, ]
可以分析出我們需要對(duì)兩中對(duì)象進(jìn)行處理,一個(gè)是數(shù)組,一個(gè)是字面量對(duì)象。
然后假如我們修改了id=1的那條記錄的‘name’屬性,‘name=張偉’,該怎么做?
首先第一步我們要找到id=1的那條記錄的index,這里是1;然后是確定需要更改的字段和更改后的值。
var update = require("immutability-helper"); const data = [ { "id": 0, name: "xiaoming" }, { "id": 1, name: "lilei" }, { "id": 2, name: "hanmeimei" }, ] const data2 = update(data, { 1: { name: { $set: "張偉" } } }); console.log(data[1]["name"], data2[1]["name"]); console.log(`data===data2: ${data===data2}`);
輸出結(jié)果:
這樣就實(shí)現(xiàn)了在源數(shù)據(jù)的基礎(chǔ)上更改了值并且輸出一個(gè)與之地址完全不同數(shù)組。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/109055.html
摘要:引言之前項(xiàng)目中遇到數(shù)據(jù)拷貝引用之間數(shù)據(jù)層級(jí)嵌套過(guò)深,拷貝的值相互之間影響的問(wèn)題,后來(lái)引入了,使用過(guò)程中的一些總結(jié),跟大家分享下,至于為什么不是,請(qǐng)看下文分解,這里是平頭哥聯(lián)盟,我是首席填坑官蘇南。 showImg(https://segmentfault.com/img/bVbiLBX?w=1008&h=298); 引言 之前項(xiàng)目中遇到數(shù)據(jù)拷貝、引用之間數(shù)據(jù)層級(jí)嵌套過(guò)深,拷貝的值相...
摘要:入門(mén)學(xué)習(xí)筆記整理一搭建環(huán)境入門(mén)學(xué)習(xí)筆記整理二簡(jiǎn)介與語(yǔ)法入門(mén)學(xué)習(xí)筆記整理三組件入門(mén)學(xué)習(xí)筆記整理四事件入門(mén)學(xué)習(xí)筆記整理五入門(mén)學(xué)習(xí)筆記整理六組件通信入門(mén)學(xué)習(xí)筆記整理七生命周期入門(mén)學(xué)習(xí)筆記整理八入門(mén)學(xué)習(xí)筆記整理九路由React 入門(mén)學(xué)習(xí)筆記整理(一)——搭建環(huán)境 React 入門(mén)學(xué)習(xí)筆記整理(二)—— JSX簡(jiǎn)介與語(yǔ)法 React 入門(mén)學(xué)習(xí)筆記整理(三)—— 組件 React 入門(mén)學(xué)習(xí)筆記整理(...
摘要:只因技術(shù)種類(lèi)繁雜眾多層出不窮,程序員只有靠不斷的學(xué)習(xí)才能不落后于技術(shù),被工作淘汰。特此推薦給大家。 99%的程序員每天都是先學(xué)習(xí),后工作,不然完成不了工作。只因技術(shù)種類(lèi)繁雜眾多、層出不窮,程序員只有靠不斷的學(xué)習(xí)才能不落后于技術(shù),被工作淘汰。我就是這其中一員,深得體會(huì)其中的「疼并快樂(lè)」,在...
摘要:實(shí)際上,在爭(zhēng)奪這個(gè)客戶過(guò)程中,這些高水平機(jī)器學(xué)習(xí)工具足以讓谷歌擊敗亞馬遜后者被普遍認(rèn)為是公有云平臺(tái)領(lǐng)域的領(lǐng)導(dǎo)者。他在大會(huì)上表示,谷歌和微軟是云端計(jì)算學(xué)習(xí)領(lǐng)域的領(lǐng)導(dǎo)者,而則在努力追趕。印象筆記并不是一家使用谷歌機(jī)器學(xué)習(xí)能力的公司。 北京時(shí)間9月15日消息,據(jù)國(guó)外媒體報(bào)道,谷歌過(guò)去幾年一直在提供公有云服務(wù),但在客戶增長(zhǎng)方面,這家搜索巨頭仍然落后于主要競(jìng)爭(zhēng)對(duì)手亞馬遜和微軟。谷歌數(shù)據(jù)中心內(nèi)部一瞥在V...
閱讀 1213·2021-10-11 10:59
閱讀 1996·2021-09-29 09:44
閱讀 886·2021-09-01 10:32
閱讀 1457·2019-08-30 14:21
閱讀 1899·2019-08-29 15:39
閱讀 3001·2019-08-29 13:45
閱讀 3562·2019-08-29 13:27
閱讀 2032·2019-08-29 12:27