美文网首页
第十七篇 描述UI-渲染列表

第十七篇 描述UI-渲染列表

作者: 深圳都这么冷 | 来源:发表于2023-02-09 00:00 被阅读0次

渲染列表

您通常希望显示数据集合中的多个相似组件。 您可以使用 JavaScript 数组方法来操作数据数组。 在此页面上,您将结合使用 filter() 和 map() 和 React 来过滤数据数组并将其转换为组件数组。

你将学习

  • 如何使用 JavaScript 的 map() 从数组中渲染组件
  • 如何使用 JavaScript 的 filter() 只渲染特定的组件
  • 何时以及为何使用 React 键key

从数组中渲染数据

假设您有一个内容列表。

<ul>
  <li>Creola Katherine Johnson: mathematician</li>
  <li>Mario José Molina-Pasquel Henríquez: chemist</li>
  <li>Mohammad Abdus Salam: physicist</li>
  <li>Percy Lavon Julian: chemist</li>
  <li>Subrahmanyan Chandrasekhar: astrophysicist</li>
</ul>

这些列表项之间的唯一区别是它们的内容和数据。 在构建界面时,您通常需要使用不同的数据显示同一组件的多个实例:从评论列表到个人资料图片库。 在这些情况下,您可以将该数据存储在 JavaScript 对象和数组中,并使用 map() 和 filter() 等方法从中呈现组件列表。

以下是如何从数组生成项目列表的简短示例:

  1. 将数据移动到数组中:
const people = [
  'Creola Katherine Johnson: mathematician',
  'Mario José Molina-Pasquel Henríquez: chemist',
  'Mohammad Abdus Salam: physicist',
  'Percy Lavon Julian: chemist',
  'Subrahmanyan Chandrasekhar: astrophysicist'
];
  1. 将 people 成员映射到一个新的 JSX 节点数组 listItems 中:
const listItems = people.map(person => <li>{person}</li>);

3.从包裹在 <ul> 中的组件返回 listItems:

return <ul>{listItems}</ul>;

这是结果:

const people = [
  'Creola Katherine Johnson: mathematician',
  'Mario José Molina-Pasquel Henríquez: chemist',
  'Mohammad Abdus Salam: physicist',
  'Percy Lavon Julian: chemist',
  'Subrahmanyan Chandrasekhar: astrophysicist'
];

export default function List() {
  const listItems = people.map(person =>
    <li>{person}</li>
  );
  return <ul>{listItems}</ul>;
}

请注意上面的沙箱显示控制台错误:

Console
 X Warning: Each child in a list should have a unique “key” prop.

您将在本页稍后了解如何修复此错误。 在这之前,让我们为您的数据添加一些结构。

过滤数组的数据项

这些数据甚至可以更加结构化。

const people = [{
  id: 0,
  name: 'Creola Katherine Johnson',
  profession: 'mathematician',
}, {
  id: 1,
  name: 'Mario José Molina-Pasquel Henríquez',
  profession: 'chemist',
}, {
  id: 2,
  name: 'Mohammad Abdus Salam',
  profession: 'physicist',
}, {
  name: 'Percy Lavon Julian',
  profession: 'chemist',  
}, {
  name: 'Subrahmanyan Chandrasekhar',
  profession: 'astrophysicist',
}];

假设您想要一种方法来只显示职业是“化学家chemist”的人。 您可以使用 JavaScript 的 filter() 方法只返回那些人。 此方法采用一组项目,通过“测试”(返回 true 或 false 的函数)传递它们,并返回仅包含通过测试(返回 true)的那些项目的新数组。

你只想要职业是“ chemist”的物品。 这个“测试”函数看起来像 (person) => person.profession === 'chemist'。 以下是如何将它们放在一起:

1.通过对 person.profession === 'chemist' 过滤的人员调用 filter() 来创建一个仅包含“化学家”人员、化学家的新数组:

const chemists = people.filter(person =>
  person.profession === 'chemist'
);

2.现在映射化学家:

const listItems = chemists.map(person =>
  <li>
     <img
       src={getImageUrl(person)}
       alt={person.name}
     />
     <p>
       <b>{person.name}:</b>
       {' ' + person.profession + ' '}
       known for {person.accomplishment}
     </p>
  </li>
);

3.最后,从您的组件返回 listItems:

return <ul>{listItems}</ul>;

utils.js

export function getImageUrl(person) {
  return (
    'https://i.imgur.com/' +
    person.imageId +
    's.jpg'
  );
}

data.js

export const people = [{
  id: 0,
  name: 'Creola Katherine Johnson',
  profession: 'mathematician',
  accomplishment: 'spaceflight calculations',
  imageId: 'MK3eW3A'
}, {
  id: 1,
  name: 'Mario José Molina-Pasquel Henríquez',
  profession: 'chemist',
  accomplishment: 'discovery of Arctic ozone hole',
  imageId: 'mynHUSa'
}, {
  id: 2,
  name: 'Mohammad Abdus Salam',
  profession: 'physicist',
  accomplishment: 'electromagnetism theory',
  imageId: 'bE7W1ji'
}, {
  id: 3,
  name: 'Percy Lavon Julian',
  profession: 'chemist',
  accomplishment: 'pioneering cortisone drugs, steroids and birth control pills',
  imageId: 'IOjWm71'
}, {
  id: 4,
  name: 'Subrahmanyan Chandrasekhar',
  profession: 'astrophysicist',
  accomplishment: 'white dwarf star mass calculations',
  imageId: 'lrWQx8l'
}];

App.js

import { people } from './data.js';
import { getImageUrl } from './utils.js';

export default function List() {
  const chemists = people.filter(person =>
    person.profession === 'chemist'
  );
  const listItems = chemists.map(person =>
    <li>
      <img
        src={getImageUrl(person)}
        alt={person.name}
      />
      <p>
        <b>{person.name}:</b>
        {' ' + person.profession + ' '}
        known for {person.accomplishment}
      </p>
    </li>
  );
  return <ul>{listItems}</ul>;
}

"陷阱

箭头函数在 => 之后隐式返回表达式,所以你不需要 return 语句:

const listItems = chemists.map(person =>
  <li>...</li> // Implicit return!
);

但是,如果 => 后跟 { 大括号,则必须显式地写 return!

const listItems = chemists.map(person => { // Curly brace
  return <li>...</li>;
});

包含 => { 的箭头函数据说有一个“块体”。 他们让你写不止一行代码,但你必须自己写一个返回语句。 如果您忘记了它,将一无所获!

使用键按顺序排列列表项

请注意,上面的所有沙箱都在控制台中显示错误:

Console
X Warning: Each child in a list should have a unique “key” prop.

您需要为每个数组项提供一个键——一个字符串或一个数字,用于在该数组的其他项中唯一标识它:

<li key={person.id}>...</li>

注意

直接在 map() 调用中的 JSX 元素总是需要key!

Key告诉 React 每个组件对应于哪个数组项,以便稍后匹配它们。 如果您的数组项可以移动(例如由于排序)、插入或删除,这就变得很重要。 一个精心选择的键可以帮助 React 推断到底发生了什么,并对 DOM 树进行正确的更新。

与其即时生成key,不如将它们包含在数据中:

import { people } from './data.js';
import { getImageUrl } from './utils.js';

export default function List() {
  const listItems = people.map(person =>
    <li key={person.id}>
      <img
        src={getImageUrl(person)}
        alt={person.name}
      />
      <p>
        <b>{person.name}</b>
          {' ' + person.profession + ' '}
          known for {person.accomplishment}
      </p>
    </li>
  );
  return <ul>{listItems}</ul>;
}

深度阅读:为每个列表项显示多个 DOM 节点

当每个项目需要呈现的不是一个而是多个 DOM 节点时,您会怎么做?

简短的 <>...</> 片段语法不允许您传递key,因此您需要将它们分组到一个 <div> 中,或者使用稍长且更明确> 的 <Fragment> 语法:

import { Fragment } from 'react';

// ...

const listItems = people.map(person =>
  <Fragment key={person.id}>
    <h1>{person.name}</h1>
    <p>{person.bio}</p>
  </Fragment>
);

片段从 DOM 中消失,因此这将生成 <h1>、<p>、<h1>、<p> 等的平坦列表。

从哪里得到你的key

不同的数据来源提供不同的密钥来源:

  • 来自数据库的数据:如果您的数据来自数据库,您可以使用本质上唯一的数据库键/ID。
  • 本地生成的数据:如果您的数据是在本地生成和保存的(例如笔记应用程序中的笔记),请在创建项目时使用递增计数器、crypto.randomUUID() 或类似 uuid 的包。

key的法则

  • key在兄弟姐妹中必须是唯一的。 但是,可以为不同数组中的 JSX 节点使用相同的键。
  • key不得更改,否则会破坏其目的! 不要在渲染时生成它们。

为何react需要key

想象一下你桌面上的文件没有名字。 相反,您可以按顺序引用它们——第一个文件、第二个文件,依此类推。 你可以习惯它,但是一旦你删除了一个文件,它就会变得混乱。 第二个文件将成为第一个文件,第三个文件将成为第二个文件,依此类推。

文件夹中的文件名和数组中的 JSX 键具有相似的用途。 它们让我们在其兄弟姐妹之间唯一地识别一个项目。 精心选择的键提供的信息比数组中的位置更多。 即使位置由于重新排序而改变,键也让 React 在其整个生命周期中识别项目。

"陷阱

您可能会想使用数组中项目的索引作为其键。 事实上,如果你根本不指定键,React 就会使用它。 但是如果一个项目被插入、删除或者数组被重新排序,你渲染项目的顺序会随着时间的推移而改变。 索引作为键通常会导致微妙且令人困惑的错误。

同样,不要即时生成key,例如 使用 key={Math.random()}。 这将导致键在渲染之间永远不会匹配,从而导致每次都重新创建所有组件和 DOM。 这不仅速度慢,而且还会丢失列表项内的任何用户输入。 相反,使用基于数据的稳定 ID。

请注意,您的组件不会接收key作为prop。 它仅用作 React 本身的提示。 如果你的组件需要一个 ID,你必须将它作为一个单独的 prop 传递:<Profile key={id} userId={id} />。

回顾

在此页面上,您了解到:

  • 如何将数据从组件中移出并移入数组和对象等数据结构中。
  • 如何使用 JavaScript 的 map() 生成一组相似的组件。
  • 如何使用 JavaScript 的 filter() 创建过滤项目数组。
  • 为什么以及如何在集合中的每个组件上设置键,以便 React 可以跟踪每个组件,即使它们的位置或数据发生变化。

相关文章

  • 第七节:React列表渲染与数据收集

    1. 列表渲染 1.1 列表渲染说明: 列表渲染 先将列表数据转为React元素列表, 然后在渲染 React会将...

  • 第七节:React列表渲染与数据收集

    1. 列表渲染 1.1 列表渲染说明: 列表渲染 先将列表数据转为React元素列表, 然后在渲染 React会将...

  • art-template

    列表渲染 条件渲染

  • React Hooks 问题 - useState 更新不渲染组

    ※ 问题描述具体操作:初始化渲染列表,点击按钮向列表中添加数据。实际效果:页面上的列表并未更新。 ※ 解决办法se...

  • 2021-11-13、列表渲染

    1、案例描述 列表渲染 2、实现过程 2.1、代码展示 wxml wxss js 2.2、结果展示 3、知识汇总 ...

  • 列表渲染

    在小程序的不同生命周期和不同的用户操作情况下,可能需要为用户展示和相应不同的内容,在这个时候,我们可以借助条件渲染...

  • 列表渲染

    1. vm.items[indexOfItem] = newValue 2. vm.items.length =...

  • 列表渲染

    用 v-for 把一个数组对应为一组元素 我们用 v-for 指令根据一组数组的选项列表进行渲染。v-for 指令...

  • 列表渲染

    1.v-for遍历数组 2.v-for遍历对象 v-for默认使用“就地复用”策略更新已渲染过的元素列表,为了跟踪...

  • 列表渲染

    基本用法 我们用v-for指令根据一组数组的选项列表进行渲染。v-for指令需要以item in items形式的...

网友评论

      本文标题:第十七篇 描述UI-渲染列表

      本文链接:https://www.haomeiwen.com/subject/pkltkdtx.html