【Svelte从入门到精通】对比篇——for

React

在React中,我们可以灵活地操作数组类型的数据,如果要把数组数据以列表的形式展示到页面上,jsx允许我们正常地使用数组支持的方法,比如map、forEach等。

function componentreturn中或者class componentrender方法的return中,我们通常直接使用map来返回列表:

javascript 复制代码
function FunctionComponent() {
  return (
    list.map((item, index) => {
      return 内容;
    })
  )
}

class ClassComponent extends React.Component {
  render() {
    return (
      list.map((item, index) => {
        return 内容;
      })
    )
  }
}
javascript 复制代码
import { useState } from "react";

export default function Page() {
  const [list] = useState([1, 2, 3]);

  return (
    <ul>
      {list.map((item, index) => {
        return <li key={index}>item - {item}</li>;
      })}
    </ul>
  );
}

React的循环列表项中,要求我们需要为每一项添加一个key值。

如果我们想使用forEach呢?以上面一个例子为例:

javascript 复制代码
import { useEffect, useState } from "react";

export default function Page() {
  const [list] = useState([1, 2, 3]);
  const [items, setItems] = useState([]);

  useEffect(() => {
    const newLists = [];
    list.forEach((item,index) => {
      newLists.push(<li key={index}>item - {item}</li>)
    });
    setItems(newLists);
  }, [list])

  return (
    <ul>
      {items}
    </ul>
  );
}

使用forEach,我们能够在数组循环时做一些复杂的逻辑。

key

React官网中详细地阐释了key在循环中的作用。我们直接演示例子:

javascript 复制代码
import { useState } from "react";

function Item(props) {
  return (
    <div className="flex mb-4">
      <label>{props.name}</label>
      <div>
        <input type="text" className="border" />
      </div>
    </div>
  );
}

export default function Page() {
  const [list, setList] = useState([
    { name: "Foo", id: 1 },
    { name: "Bar", id: 2 },
  ]);

  const addItem = () => {
    const id = +new Date();

    setList([{ name: "Random" + id, id }, ...list]);
  };

  return (
    <div className="text-black">
      <button className="border p-2" onClick={addItem}>add item</button>
      <h3>
        Dangerous <code>key=index</code>
      </h3>
      <form>
        {list.map((todo, index) => (
          <Item {...todo} key={index} />
        ))}
      </form>
      <h3>
        Better <code>key=id</code>
      </h3>
      <form>
        {list.map((todo) => (
          <Item {...todo} key={todo.id} />
        ))}
      </form>
    </div>
  );
}

我们可以看到,我们在两个不同的列表中,同样是在Foo输入框中输入值,但使用index作为key的输入框,在添加了新的输入框后,表现异常,原来在Foo输入框的值,一直存在在第一个输入框中,而使用id作为key的输入框则表现正常。

key可以帮助React识别出哪些元素改变了,比如被添加或删除。如果列表项目的顺序可能会变化,不建议使用索引来用作key值,因为这样做会导致性能变差,还可能引起组件状态的问题。这种异常表现在Vue和Svelte中都存在。

Vue

html 复制代码
<template>
  <ul>
    <li v-for="(item, index) in list" :key="index">item - {{ item }}</li>
  </ul>
</template>

<script setup>
import { reactive } from "vue";

const list = reactive([1, 2, 3]);
</script>

在Vue中,使用v-for来进行数组循环,同样要求在循环项中绑定key,以:key=""的形式。

key

同样以上面的例子来展示:

html 复制代码
<!-- Child.vue -->
<template>
  <div class="flex mb-4">
    <label>{{ name }}</label>
    <div>
      <input type="text" class="border" />
    </div>
  </div>
</template>

<script>
export default {
  props: {
    name,
  },
};
</script>
html 复制代码
<template>
  <div class="text-black">
    <button class="border p-2" @click="addItem">add item</button>
    <h3>Dangerous <code>key=index</code></h3>
    <form>
      <Item v-for="(todo, index) in list" :name="todo.name" :key="index" />
    </form>
    <h3>Better <code>key=id</code></h3>
    <form>
      <Item v-for="(todo, index) in list" :name="todo.name" :key="todo.id" />
    </form>
  </div>
</template>

<script>
import Item from "./Child.vue";

export default {
  data() {
    return {
      list: [
        { name: "Foo", id: 1 },
        { name: "Bar", id: 2 },
      ],
    };
  },
  methods: {
    addItem() {
      const id = +new Date();
      this.list = [{ name: "Random" + id, id }, ...this.list];
    },
  },
  components: {
    Item,
  },
};
</script>

Svelte

html 复制代码
<script>
  const list = [1,2,3];
</script>

<ul>
  {#each list as item, index (key)}
    <li>item - {item}</li>
  {/each}
</ul>

在Svelte中,循环的功能放在{#each}{/each}中,key是可选的。

key

同样以相同的例子举例:

html 复制代码
<script>
// Child.svelte
  export let name;
</script>

<div class="flex mb-4">
  <label>{name}</label>
  <div>
    <input type="text" class="border" />
  </div>
</div>
html 复制代码
<script>
  import Item from './Child.svelte';

  let list = [{ name: "Foo", id: 1 },
    { name: "Bar", id: 2 }]

  const addItem = () => {
    const id = +new Date();

    list = [{ name: "Random" + id, id }, ...list]
  };
</script>

<div class="text-black">
  <button class="border p-2" on:click={addItem}>add item</button>
  <h3>
    Dangerous <code>key=index</code>
  </h3>
  <form>
    {#each list as todo}
      <Item {...todo} />
    {/each}
  </form>
  <h3>
    Better <code>key=id</code>
  </h3>
  <form>
    {#each list as todo (todo.id)}
      <Item {...todo} />
    {/each}
  </form>
</div>

小结

本章我们对比了:

  • React通过数组的map方法来实现循环列表功能
  • Vue通过v-for的方式来实现循环列表功能
  • Svelte通过{#each}{/each}来实现循环列表的功能
  • key在循环中的重要性。
相关推荐
迷雾漫步者35 分钟前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-1 小时前
验证码机制
前端·后端
燃先生._.2 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖3 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235243 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240254 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar4 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人5 小时前
前端知识补充—CSS
前端·css
GISer_Jing5 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试