• React文档(九)list和key


    首先,我们回顾一下在js里如何转换数组。

    给出下面的代码,我们使用map()函数来获取一个数组的numbers然后将值变成两倍大。我们分配新数组由map()返回:

    const numbers = [1, 2, 3, 4, 5];
    const doubled = numbers.map((number) => number * 2);
    console.log(doubled);

    这段代码在控制台输出[2, 4, 6, 8 ,10]。

    在React里,把数组转变成一系列元素也是一样的。

    渲染多个组件

    通过使用花括号,你可以创建一组元素,并且把它们包含在JSX里。

    下面,我们对numbers数组使用map()函数。为每一项返回一个<li>元素。最后,我们将元素数组处理的结果存为listItems:

    const numbers = [1, 2, 3, 4, 5];
    const listItems = numbers.map((number) =>
      <li>{number}</li>
    );

    我们将整个listItems数组放进一个<ul>元素里,然后把它渲染到DOM里:

    ReactDOM.render(
      <ul>{listItems}</ul>,
      document.getElementById('root')
    );

    在CodePen里试一试

    这段代码展示了一个1到5的数字列表。

    基础列表组件

    通常你会将列表渲染到一个组件里。

    我们可以重构上一个例子到一个组件里,这个组件接受一个number数组,输出一个无序的元素列表。

    function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
        <li>{number}</li>
      );
      return (
        <ul>{listItems}</ul>
      );
    }
    
    const numbers = [1, 2, 3, 4, 5];
    ReactDOM.render(
      <NumberList numbers={numbers} />,
      document.getElementById('root')
    );

    当你运行这段代码 ,你会看到一个警告,一个key需要提供给列表。“key”是一个特殊的字符串属性当你创建列表元素的时候你所需要的属性。在下一章节会讨论为什么这个属性很重要。

    让我们在numbers.map()里分配一个key给列表元素来修复没有key的问题。

    function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
        <li key={number.toString()}>
          {number}
        </li>
      );
      return (
        <ul>{listItems}</ul>
      );
    }
    
    const numbers = [1, 2, 3, 4, 5];
    ReactDOM.render(
      <NumberList numbers={numbers} />,
      document.getElementById('root')
    );

    在CodePen里试一试

    keys

    key帮助React鉴别哪一项发生了改变,添加了,或者移除了。key应该添加在数组里的元素身上作为一个稳定的特性。(我靠,这个是不是和html里的自定义属性很像啊)

    const numbers = [1, 2, 3, 4, 5];
    const listItems = numbers.map((number) =>
      <li key={number.toString()}>
        {number}
      </li>
    );

    key最好的方式是用一个字符串唯一地标识一个列表的项。多数情况你会使用数据的ID来作为key: 

    const todoItems = todos.map((todo) =>
      <li key={todo.id}>
        {todo.text}
      </li>
    );

    当你的数据没有稳定的ID,也许会用数据项的索引作为key:

    const todoItems = todos.map((todo, index) =>
      // Only do this if items have no stable IDs
      <li key={index}>
        {todo.text}
      </li>
    );

    如果数据项可以重排序我们不建议使用索引作为key,因为那样会降低速度。也许你可以读一读这篇深入理解为何key很重要

    依据key提取组件

    元素的key只有在它和它的兄弟节点对比时才有意义。

    举个例子,如果你提取了一个ListItem组件,你应该保持key在数组里的<listItem />元素里而不是在ListItem的<li>元素里。

    例子:错误的用法

    function ListItem(props) {
      const value = props.value;
      return (
        // Wrong! There is no need to specify the key here:
        <li key={value.toString()}>
          {value}
        </li>
      );
    }
    
    function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
        // Wrong! The key should have been specified here:
        <ListItem value={number} />
      );
      return (
        <ul>
          {listItems}
        </ul>
      );
    }
    
    const numbers = [1, 2, 3, 4, 5];
    ReactDOM.render(
      <NumberList numbers={numbers} />,
      document.getElementById('root')
    );

    例子:正确的用法

    function ListItem(props) {
      // Correct! There is no need to specify the key here:
      return <li>{props.value}</li>;
    }
    
    function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
        // Correct! Key should be specified inside the array.
        <ListItem key={number.toString()}
                  value={number} />
      );
      return (
        <ul>
          {listItems}
        </ul>
      );
    }
    
    const numbers = [1, 2, 3, 4, 5];
    ReactDOM.render(
      <NumberList numbers={numbers} />,
      document.getElementById('root')
    );

    在CodePen里试一试

    好的做法就是在map()方法调用里面的元素需要key。

    key必须唯一

    key跟兄弟节点比较的时候必须唯一。然而不需要全局唯一。当我们创建两个数组的时候可以出现相同的key。

    function Blog(props) {
      const sidebar = (
        <ul>
          {props.posts.map((post) =>
            <li key={post.id}>
              {post.title}
            </li>
          )}
        </ul>
      );
      const content = props.posts.map((post) =>
        <div key={post.id}>
          <h3>{post.title}</h3>
          <p>{post.content}</p>
        </div>
      );
      return (
        <div>
          {sidebar}
          <hr />
          {content}
        </div>
      );
    }
    
    const posts = [
      {id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
      {id: 2, title: 'Installation', content: 'You can install React from npm.'}
    ];
    ReactDOM.render(
      <Blog posts={posts} />,
      document.getElementById('root')
    );

    在CodePen里试一试

    key对React来说就是一个提示但是它们没有传递给你的组件。如果你需要同样的值在你的组件里,那就换一个不同的名字把它作为props传递:

    const content = posts.map((post) =>
      <Post
        key={post.id}
        id={post.id}
        title={post.title} />
    );

    通过上面的例子,Post组件可以读取props.id这个属性,而不是props.key。

    在JSX中嵌入map()

     在之前的例子里我们在JSX里声明了单独的listItems变量:
    function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
        <ListItem key={number.toString()}
                  value={number} />
      );
      return (
        <ul>
          {listItems}
        </ul>
      );
    }

    JSX允许嵌入任何表达式在花括号里因此我们能够内嵌map()直接到ul里面:

    function NumberList(props) {
      const numbers = props.numbers;
      return (
        <ul>
          {numbers.map((number) =>
            <ListItem key={number.toString()}
                      value={number} />
          )}
        </ul>
      );
    }
    有些时候这样写可以让你的代码更清晰,但是这个风格也能被滥用。就像在js里,决定是否有必要提取一个变量这取决于你。记住如果map()嵌套太深,也许是时候该提取一个组件了。
  • 相关阅读:
    正则表达式
    爬虫原理和网页构造
    简单的博客系统之二
    配置编辑器geany
    linux删除多文件
    eNSP交换路由基础
    NTP centOS6.5
    shell脚本之lftp上传
    进度条
    maketrans与translate函数
  • 原文地址:https://www.cnblogs.com/hahazexia/p/6406955.html
Copyright © 2020-2023  润新知