鴻蒙開發(fā):ForEach中為什么鍵值生成函數(shù)很重要

前言

在列表組件使用的時候恬汁,如List伶椿、Grid、WaterFlow等氓侧,循環(huán)渲染時都會使用到ForEach或者LazyForEach脊另,當(dāng)然了,也有單獨(dú)使用的場景约巷,如下偎痛,一個很簡單的列表組件使用,這種使用方式独郎,在官方的很多案例中也多次出現(xiàn)踩麦,相信在實際的開發(fā)中多多少少也會存在。

List({ space: 20, initialIndex: 0 }) {
      ForEach(["條目1", "條目2", "條目3", "條目4", "條目5", "條目6"], (item: string) => {
        ListItem() {
          Text(item)
            .width('100%')
            .height(50)
            .fontSize(16)
            .fontColor(Color.White)
            .textAlign(TextAlign.Center)
            .backgroundColor(Color.Orange)
        }
      }, (item: string) => item)
    }.padding({ left: 20, right: 20 })

以上的代碼氓癌,看上去也沒啥問題谓谦,UI也能正常的展示出來,如下圖:

仿佛這一切都是正確的顽铸,但是茁计,以上的代碼會存在一定的問題,那就是渲染非預(yù)期谓松, 我們繼續(xù)驗證問題所在星压,增加一個按鈕,用來添加數(shù)據(jù)鬼譬,當(dāng)然了這里需要把數(shù)據(jù)源提取至成員變量娜膘,并用@State裝飾器進(jìn)行修飾:

 @State list: string[] = ["條目1", "條目2", "條目3", "條目4", "條目5", "條目6"]

  build() {
    Column() {
      Button("追加數(shù)據(jù)").onClick(() => {
        this.list.push("條目七")
        this.list.push("條目八")
      })
      List({ space: 20, initialIndex: 0 }) {
        ForEach(this.list, (item: string) => {
          ListItem() {
            Text(item)
              .width('100%')
              .height(50)
              .fontSize(16)
              .fontColor(Color.White)
              .textAlign(TextAlign.Center)
              .backgroundColor(Color.Orange)
          }
        }, (item: string) => item)
      }.padding({ left: 20, right: 20 })
      .margin({ top: 20 })
    }
  }

當(dāng)我們點擊追加數(shù)據(jù)按鈕時,正常的情況會是优质,數(shù)組中增加數(shù)據(jù)竣贪,驅(qū)動UI更新军洼,List組件應(yīng)該會增加【條目七,條目八】兩條數(shù)據(jù)演怎。

確實匕争,點擊后,UI發(fā)生了變化爷耀,列表中增加了兩條數(shù)據(jù):

有問題嗎甘桑? 說了一大堆,程序這不執(zhí)行挺正常的歹叮,哎跑杭,稍安勿躁,我們再次點擊一下咆耿,正常的程序德谅,會再次增加兩條數(shù)據(jù),對吧萨螺?

但是窄做,問題來了,沒有增加P加亍=摺!惹盼,點擊一百次也沒有增加庸汗。

難道是重復(fù)的數(shù)據(jù)不能重復(fù)添加?這就很扯了吧手报,列表中不能出現(xiàn)重復(fù)的數(shù)據(jù)蚯舱,這在任何一個系統(tǒng)中都是聞所未聞的奇觀。

顯然這些問題都不是掩蛤,問題的原因就在于枉昏,循環(huán)的第三個參數(shù):keyGenerator。

本文的主要內(nèi)容如下:

1揍鸟、了解循環(huán) ForEach/LazyForEach三個參數(shù)

2兄裂、了解 鍵值生成規(guī)則

3、禁止渲染非預(yù)期情況

4阳藻、正確使用鍵值

5晰奖、使用相關(guān)總結(jié)


一、了解循環(huán)ForEach/LazyForEach三個參數(shù)

 (arr: Array<any>, itemGenerator: (item: any, index: number) => void, keyGenerator?: (item: any, index: number) => string): ForEachAttribute;

第一個參數(shù)arr是數(shù)據(jù)源腥泥,用來渲染UI的數(shù)據(jù)匾南,非常重要,渲染多少數(shù)據(jù)蛔外,動態(tài)增加數(shù)據(jù)蛆楞,都是和它有著直接的關(guān)系溯乒,可以是任何類型的數(shù)組源,比如對象豹爹,字符串裆悄,數(shù)值,都可以臂聋。

第二個參數(shù)itemGenerator灯帮,是組件生成函數(shù),目的為數(shù)組中的每個元素創(chuàng)建對應(yīng)的組件逻住,它是和第一個數(shù)據(jù)源是一一對應(yīng)的。

第三個參數(shù)keyGenerator迎献,是鍵值生成函數(shù)瞎访,為數(shù)據(jù)源arr的每個數(shù)組項生成唯一且持久的鍵值,其返回值吁恍,可以自己定義扒秸,如果自己定義,一定要是唯一的冀瓦,如果不定義伴奥,會是默認(rèn)的:(item: T, index: number) => { return index + '__' + JSON.stringify(item); },默認(rèn)的也能滿足大部分的需求翼闽,所以拾徙,在實際的開發(fā)中,如果你很難決定唯一感局,那么直接用默認(rèn)的就行尼啡。在前言中的問題,就是因為鍵值不唯一造成的询微。

二崖瞭、了解鍵值生成規(guī)則

通過了解循環(huán)的三個參數(shù),我們已經(jīng)知道了撑毛,系統(tǒng)會為我們提供設(shè)置鍵值的函數(shù)參數(shù)书聚,可以使用自定義的,當(dāng)然也可以使用默認(rèn)的鍵值生成規(guī)則藻雌,也就是item: Object, index: number) => { return index + '__' + JSON.stringify(item); }雌续。

在實際的渲染過程中,每個數(shù)組元素生成一個唯一且持久的鍵值蹦疑,用來標(biāo)記相對應(yīng)的組件西雀,當(dāng)鍵值有變化時,ArkUI框架會認(rèn)為歉摧,當(dāng)前數(shù)組元素替換或修改艇肴,會根據(jù)新的鍵值重新創(chuàng)建一個新的組件腔呜。

鍵值的生成規(guī)則,直接會影響著數(shù)據(jù)渲染的UI再悼,因為第二個參數(shù)itemGenerator函數(shù)會根據(jù)鍵值生成規(guī)則為數(shù)據(jù)源的每個數(shù)組項創(chuàng)建組件核畴。

在前言的Demo中,可以發(fā)現(xiàn)冲九,每個組件的鍵值為當(dāng)前的數(shù)據(jù)源谤草,當(dāng)不同數(shù)組項按照鍵值生成規(guī)則生成的鍵值相同時,框架認(rèn)為是未定義的莺奸,此時不再創(chuàng)建新的組件丑孩, 也就是點擊不會再次創(chuàng)建組件的原因。

當(dāng)然了灭贷,還有一種情況温学,那就是,在已有的數(shù)據(jù)上進(jìn)行修改甚疟,比如有三條數(shù)據(jù)仗岖,把第三條數(shù)據(jù)修改為新的數(shù)據(jù)源,這種情況览妖,前兩個數(shù)據(jù)轧拄,F(xiàn)orEach會復(fù)用進(jìn)行渲染,第三個則會為該數(shù)組項創(chuàng)建了一個新的組件讽膏。

三檩电、禁止渲染非預(yù)期情況

什么叫渲染非預(yù)期?前言中的Demo就是一個典型的案例府树,存在相同鍵值是嗜,因此不會創(chuàng)建新組件,在實際的開發(fā)中挺尾,使用ForEach時應(yīng)盡量避免最終鍵值生成規(guī)則中包含index鹅搪,或者使用不唯一的規(guī)則作為鍵值。

四遭铺、正確使用鍵值

首先丽柿,必須滿足鍵值的唯一性,這一點毋庸置疑魂挂,必須要設(shè)置正確甫题,如果使用的是對象,強(qiáng)烈建議涂召,使用對象中的唯一值坠非,比如id作為鍵值。

如果是使用基本類型的數(shù)據(jù)作為鍵值果正,一定要確保數(shù)組中的元素是沒有重復(fù)的炎码,否則就會出現(xiàn)前言Demo中的問題盟迟,另外,在使用基本類型鍵值潦闲,F(xiàn)orEach在改變數(shù)據(jù)源后會重新創(chuàng)建組件攒菠,這會帶來一定的性能損耗問題。

根據(jù)官方的解讀歉闰,在使用ForEach的時候辖众,盡量不要與LazyForEach混合使用,這是官方所不推薦的和敬,切記凹炸!

五、使用相關(guān)總結(jié)

為了使得數(shù)據(jù)渲染正確昼弟,請一定要確保第三個參數(shù)鍵值的唯一性还惠,另外除非必要,不推薦將第三個參數(shù)KeyGenerator函數(shù)處于缺省狀態(tài)私杜,以及在鍵值生成規(guī)則中包含數(shù)據(jù)項索引index。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末救欧,一起剝皮案震驚了整個濱河市衰粹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌笆怠,老刑警劉巖铝耻,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蹬刷,居然都是意外死亡瓢捉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門办成,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泡态,“玉大人,你說我怎么就攤上這事迂卢∧诚遥” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵而克,是天一觀的道長靶壮。 經(jīng)常有香客問我,道長员萍,這世上最難降的妖魔是什么腾降? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮碎绎,結(jié)果婚禮上螃壤,老公的妹妹穿的比我還像新娘抗果。我一直安慰自己,他們只是感情好映穗,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布窖张。 她就那樣靜靜地躺著,像睡著了一般蚁滋。 火紅的嫁衣襯著肌膚如雪宿接。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天辕录,我揣著相機(jī)與錄音睦霎,去河邊找鬼。 笑死走诞,一個胖子當(dāng)著我的面吹牛副女,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蚣旱,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼碑幅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了塞绿?” 一聲冷哼從身側(cè)響起沟涨,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎异吻,沒想到半個月后裹赴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诀浪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年棋返,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雷猪。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡睛竣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出求摇,到底是詐尸還是另有隱情酵颁,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布月帝,位于F島的核電站躏惋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嚷辅。R本人自食惡果不足惜簿姨,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧扁位,春花似錦准潭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至暇务,卻和暖如春泼掠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背垦细。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工择镇, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人括改。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓腻豌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嘱能。 傳聞我的和親對象是個殘疾皇子吝梅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

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