国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

React 中的列表渲染為什么要加Key

開發 前端
對于列表的渲染,我們有必要提供 key,來對節點進行區分,React 的 DOM Diff 算法會基于 key 進行節點位置的調整,確保一些涉及到內部狀態的節點的渲染狀態。

大家好,我是前端西瓜哥,今天來學習 React 中的列表渲染要加 key 的原因。

在 React 中我們經常需要渲染列表,比如展示好友列表。

常用寫法是用 Arrary.prototype.map 方法,將數組形式的數據映射為 JSX.Element 數組,并嵌入到組件要返回的 JSX.Element 中,如下:

function FriendList() {
const [items, setItems] = useState(['前端西瓜哥', '小明', '張三']);
return (
<ul>
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
);
}

你需要給每個項提供 key 屬性作為標識,以區分不同的項。如果你不加 key,React 會警告你:

Warning: Each child in a list should have a unique "key" prop.

為什么需要 key?

在回答這個問題之前,我們先簡單了解一下 React 的 DOM Diff 算法原理。

React 會在狀態發生變化時,對真實 DOM 樹按需批量更新,產生新的 UI。

為此底層做的工作是:將新舊兩棵虛擬 DOM 樹進行 diff 對比,計算出 patch 補丁,打到真實 DOM 樹上。

為了高效,React 的 diff 算法做了限制:

  1. 只做同層級的節點對比,不跨層級比較。
  2. 如果元素的類型不同(如從 p 變成 div),那它們就是不相同的,會銷毀整個舊子樹,并調用其下組件的卸載鉤子,然后再創建全新的樹,相當消耗性能。
  3. 如果類型相同,會進行打補丁操作(如更新 className 和標簽下的文本內容)。

但這樣做會有一個問題,如果同級的多節點 只是位置發生了變化,但因為相同索引位置對不上,又發現不能復用,就要銷毀一棵樹并創建一棵新樹,實在是太過于低效了。

于是 React 給開發者提供 key 來標記節點,來優化 React diff 算法,告知 React 某個節點其實沒有被移除或不能被原地復用,只是換了位置而已,讓 React 更新一下位置。

列表渲染不提供 key 會怎樣?

不提供 key,React 就無法確定某個節點是否移動了。

React 就只會對比相同位置的兩個節點,如果它們類型相同(比如都是 li 元素),就會對比 props 的不同,進行 props 的打補丁。

因為 列表渲染通常都是相同的類型,所以位置變動時,多半是會觸發節點原地復用效果,倒是不用擔心樹的銷毀重建發生。

原地復用在不提供 key 的時候有時候也是能正確渲染的。

除了一種情況,就是 這個節點有自己的內部狀態,最經典的莫過于輸入框。

function FriendList() {
const [items, setItems] = useState(['前端西瓜哥', '小明', '張三']);
const swap = () => {
[items[0], items[1]] = [items[1], items[0]];
setItems([...items]);
};
return (
<div>
<ul>
{items.map((item) => (
<li>{item}<input /></li>
))}
</ul>
<button onClick={() => { swap(); }}>
交換
</button>
</div>
);
}

我們給第一和第二個輸入框輸入內容。

React 中的列表渲染為什么要加 key?

再點擊 “交換” 按鈕,交換數組第一和第二個元素位置。

然后我們看到 input 前面的文字正確交換了,但是輸入框里的內容卻沒有交換。

React 中的列表渲染為什么要加 key?

原因是 React 做了原地復用,而 input 沒有傳 props,不需要打 props 補丁,保持了原樣。

這個問題怎么解決?加 key。讓 React 知道你的節點需要移動,你得這樣寫:

items.map((item) => (
<li key={item}>{item}<input /></li>
))

不使用 key 的另一個缺點是:因為原地復用會使傳入的 props 發生變化,導致不能利用好 React.memo 的組件緩存能力。

列表渲染的 key 用數組索引會怎樣?

效果和不使用 key 相同,依舊是新舊節點的相同索引位置對比,但是控制臺不會打印警告。

應該用什么值作為 key?

對于節點,你需要用一個唯一的 id 賦值給 key,通常會是數組的 id,比如后端返回的好友列表的好友 id。

const [items, setItems] = useState([
{ id: 5, name: '前端西瓜哥' },
{ id: 9, name: '小明' },
{ id: 87, name: '張三' },
{ id: 91, name: '前端西瓜哥' }
]);
const list = items.map((item) => (
<li key={item.id}>{item.name}</li>
));

如果后端沒有返回 id,你可以自己手動用一個 id 生成器補上一個 id,雖然不太優雅就是了。比如:

const items = ['前端西瓜哥', '張三'];
const genId = (() => {
let i = 0;
return () => {
return i++;
}
})();
const itemsWithId = items.map(item => ({ id: genId(), val: item }));
// [{id: 0, val: '前端西瓜哥'}, {id: 1, val: '張三'}]

對了,這個 key 只需要在同一個層級的節點唯一即可,不要求所有層級的 key 都是唯一的。

另外,如果你確保你的列表渲染后直到被銷毀,不會有位置上的變化,可以使用數組索引為 key。

結尾

對于列表的渲染,我們有必要提供 key,來對節點進行區分,React 的 DOM Diff 算法會基于 key 進行節點位置的調整,確保一些涉及到內部狀態的節點的渲染狀態。

通常來說,key 值應該是唯一的,通常來自后端返回的數據。在你確認列表不會發生位置變更時,可以使用數組索引作為 key,以去掉惱人的警告提示。

有一個點需要說明的是,key 并不是列表渲染的專屬,普通的節點也可以用 key。

責任編輯:姜華 來源: 今日頭條
相關推薦

2022-06-09 08:32:21

SQLNOLOCKWITH

2021-09-14 10:48:13

SQL Nolock代碼

2023-04-06 08:43:29

SQLWITH(NOLOCK

2022-11-15 08:35:00

SQLNOLOCK數據

2024-01-29 09:01:20

React列表模式

2020-06-16 08:17:11

代碼空格開發

2020-03-03 15:31:47

ReactVue前端

2021-07-06 07:27:45

React元素屬性

2019-08-28 16:38:49

finalJava編程語言

2025-09-03 01:55:00

2015-08-06 10:14:15

造輪子facebook

2022-08-15 08:27:02

基站網絡

2013-03-12 14:30:09

Ubuntu操作系統

2023-05-09 07:16:06

2022-05-10 09:14:15

React 并發渲染

2019-11-27 10:25:15

SaaS云端IT架構

2017-04-05 16:40:45

2021-02-11 13:30:56

Nodejs源碼c++

2015-05-12 11:04:42

Java EE學習Java EE

2024-10-17 16:41:57

KafkaZooKeeper
點贊
收藏

51CTO技術棧公眾號

国产精品美女www爽爽爽视频| 欧美亚洲三区| 亚洲精品一区二区在线看| 国产精品免费免费| 日韩美女视频在线观看| 中文字幕在线中文字幕二区| 日韩国产一区| 日韩欧美电影一区| 男人天堂av片| 欧美freesex8一10精品| 国模少妇一区二区三区| 国产精品免费人成网站| 亚洲丁香婷深爱综合| 日韩欧美电影一区二区| 免费视频观看成人| 精品美女永久免费视频| 91麻豆蜜桃| 欧美精品久久久久久久久25p| 99综合电影在线视频| 最新黄网在线观看| 日本欧美一区二区| 国产性色av一区二区| 66av99| 99精品网站| 最近2019年好看中文字幕视频 | 影音先锋可以看的网站| 亚洲理伦在线| 欧美一区二区三区啪啪| 国产美女久久精品| 日韩中文不卡| 欧美变态挠脚心| 欧美日精品一区视频| 午夜电影福利网| 国产一区二区影院| 国产精品久久久久久久久久久久久久 | 欧美一区视久久| 首页国产精品| 国产精品久久久久久久久久小说 | 免费一级欧美在线观看视频| 日韩在线视频线视频免费网站| 国产精品久久久久久久久免费高清 | 亚洲午夜天堂| 亚洲国产女人aaa毛片在线| 香蕉成人app免费看片| 亚洲精品福利资源站| 成人全视频免费观看在线看| 在线观看免费高清视频97| 精品一区二区三区中文字幕视频| 久久久免费在线观看| 久久电影院7| 亚洲永久激情精品| 91一区二区三区在线播放| 曰本人一级毛片免费完整视频| 欧美体内she精视频| 成人欧美一区二区三区的电影| 欧美成人激情视频| 久久亚洲精品中文字幕蜜潮电影| 久久精品国产精品青草色艺| 国产aⅴ综合色| 狠狠干五月天| 91精品国产综合久久久久久 | 九九热视频在线观看| 国产成人精品999| 国产肥臀一区二区福利视频| 成人激情黄色小说| 777精品久无码人妻蜜桃| 一色桃子久久精品亚洲| 伊人色综合久久天天| 日韩精品―中文字幕| 国产日韩欧美在线一区| 在线午夜视频| 一区二区三区中文字幕电影| 国产精品一区二区三区四区色| 亚洲综合一二区| 婷婷午夜社区一区| 亚洲卡通动漫在线| 国产精品免费视频一区二区| 欧洲xxxxx| 中文字幕第一区二区| 性网站在线看| 欧美va亚洲va国产综合| 一区二区日韩| 444亚洲人体| 成人午夜电影久久影院| 香蕉视频免费在线| 中文字幕精品网| 欧洲三级视频| 99久re热视频精品98| 五月综合激情婷婷六月色窝| 丝袜老师在线| 3d精品h动漫啪啪一区二区| 国产在线看一区| 黄色片在线播放| 久久躁日日躁aaaaxxxx| 亚洲另类黄色| 少妇激情av一区二区三区| 一本色道久久综合狠狠躁篇的优点| 亚洲大胆在线| 狠狠v欧美ⅴ日韩v亚洲v大胸| 天堂成人免费av电影一区| 久久亚洲综合国产精品99麻豆精品福利| 精品日韩av| 国产精品18久久久久久麻辣| 国产情人综合久久777777| 久久国产精品免费| 四虎影视2018在线播放alocalhost| 亚洲国产精品va| 欧美+亚洲+精品+三区| 亚洲欧美自拍另类日韩| 亚洲天堂免费观看| 噜噜噜躁狠狠躁狠狠精品视频| 欧美aaa大片| 欧美交受高潮1| 成人动漫视频在线| 黄色视屏在线免费观看| 精品一区二区三区自拍图片区| 一区二区三区四区蜜桃| 久久精品九色| 激情深爱综合网| 亚洲人成欧美中文字幕| 男男视频亚洲欧美| 国产一二区在线| 国产精品v欧美精品v日韩精品| 亚洲精品免费在线观看| 999在线精品| 免费大片在线观看| 色老头一区二区三区| 免费的国产精品| 婷婷在线播放| 日韩精彩视频| 欧美日韩dvd在线观看| 午夜欧美理论片| 在线观看视频你懂的| 国产欧美久久久久久| 亚洲午夜精品网| 国产精品久久久久久影院8一贰佰 国产精品久久久久久麻豆一区软件 | 亚洲精品无人区| 在线成人av网站| 99久久精品国产精品久久| 国产一区二区亚洲| 激情视频在线观看| 五月婷婷开心综合| 人妻少妇精品无码专区二区| jizz18女人| 亚洲欧美一区二区三区情侣bbw| 国产综合色产在线精品| 欧美电影免费观看| 欧美大片在线播放| 欧美日韩国产va另类| 国产精品久久久一本精品| 国产精品三级| 成人动漫视频| 91精品久久久久久综合五月天| 在线观看高清av| 少妇精品久久久久久久久久| 欧美激情图片区| www.色综合| 亚洲日本护士毛茸茸| 成人免费淫片在线费观看| 欧美精品情趣视频| 亚洲第一级黄色片| 亚洲一区二区三区中文字幕 | 欧美日韩尤物久久| 精品综合久久| 日韩亚洲欧美中文在线| 日韩欧美一级二级| 久久久这里只有精品视频| 青青草原国产免费| 成人精品影院| 深夜影院在线观看| 精品国产_亚洲人成在线| 91麻豆精品国产91久久久久| 久久亚洲精品伦理| se01亚洲视频| 综合激情丁香| 91精品视频免费看| 精品免费国产一区二区三区四区| 国产日本在线播放| 999热视频| 丁香五月网久久综合| 欧美一区二区三区四区在线| 在线看国产精品| 日韩欧美在线123| 91福利精品视频| 1024成人网| 日韩亚洲欧美一区二区三区| 视频一区二区三区在线观看| 日韩一中文字幕| 欧美天天综合色影久久精品| 国产一区二区网址| 自拍视频一区| а√天堂官网中文在线| 久草精品在线播放| 国产亚洲欧美一区二区三区| 日韩中文字幕在线精品| 91福利在线看| 国产精品三级视频| 丝袜美腿一区二区三区| 日韩美脚连裤袜丝袜在线| bl视频在线免费观看|