Nuxt 3/Vue 3 反应性问题,在 v-for 循环中渲染组件时

问题描述 投票:0回答:1

嘿社区:)我有一个反应性问题(我认为这与反应性有关)。

描述

我有

FileInput.vue
组件。使用该组件,我将文件上传到项目。添加新图像时,新字段将推送到
form.allImages reactive
数组:

@add="addImageField"

addImageField 函数:

const addImageField = (): void => {
  form.allImages.push({ filename: '' });
};

反应数据:

import type { Images } from '@/types/images.d';

interface Work {
  allImages: Images[];
}

const form: Work = reactive({
  allImages: [{ filename: '' }],
});

问题描述

当我添加 2 个图像,然后尝试使用以下方法删除第一个图像时:

const deleteImageField = (index: number): void => {
   form.allImages.splice(index, 1);
};

第一个块正在正确删除,第二个块到达其位置(这是正确的),但现在第二个图像块需要为空(具有明确的值才能向其添加图像)。

form.allImages
中第二个元素的值是清楚的,但组件块不为空,仍然保留了现在是数组中第一个元素的块的图像。

图片:https://github.com/nuxt/nuxt/assets/73745478/74981582-05ea-4910-9387-7240dc4394c2

复制

https://stackblitz.com/edit/nuxt-starter-qeaaeuf?file=app.vue 这是复制品。

如何使用复制品

单击

Add Image
块并从您的电脑中选择任何图像,将显示
static favicon.ico
文件仅用于示例。然后会出现
Delete
按钮用于删除该图像。在所有块上方,您可以看到用于跟踪数据的
{{ form.allImages }}
数据块。

它应该如何工作

删除后,值为空的图片块需要为空(不包含任何图片,并且能够让用户上传图片)。

**感谢您的关注。如果可以的话请帮忙:)

附注如果您有任何改进代码的想法,也可以写出来。谢谢。**

javascript vue.js frontend nuxt.js
1个回答
0
投票

v-for

key
需要与
v-for
位于同一元素上。不仅如此,您 不应该使用
index
作为您的
v-for
。键应该是唯一的值。当您有一个要添加和删除元素的数组时,每个索引处的项目可能会更改,这意味着索引不是给定项目的唯一标识符。这就是 UI 无法正确更新的原因。 Vue 无法根据键正确区分数组的更改。

纠正此问题的一种简单方法是添加一个基于计数器变量的唯一

id
字段,每次推送到数组时该变量都会增加。

interface Images {
  filename: string
  id: number
}

let count = ref(0);
const form: Work = reactive({
  allImages: [{ id: count.value++, filename: '' }],
});

const addImageField = (): void => {
  form.allImages.push({ id: count.value++, filename: '' });
};

那么你的 v-for 应该是:

<div v-for="(image, index) in form.allImages" :key="image.id" 

更新了 StackBlitz


纠正了一些其他问题:

const { text, required, modelValue } = props;
  1. 请勿破坏道具。这将导致这些值失去其反应性。如果您使用

    setup()
    功能,则可以使用
    props.propName
    访问它们。或者在设置函数之外作为
    this.propName
    ,或者在模板代码中作为
    propName
    。您也不必从设置函数返回道具。它们会自动为您退回。

  2. 您应该重命名自定义按钮组件。 “Button”是 HTML 中原生

    <button>
    元素的保留名称。

© www.soinside.com 2019 - 2024. All rights reserved.