Vue项目中v-for数组删除第n项元素产生渲染错误问题及解决方法

数据治
• 阅读 13910

项目背景

最近使用Vue(版本2.9)开发一个项目时,要生成表单列表,所以使用了v-for来做循环,循环里的元素(item)是一个子组件。同时每个元素都有删除按钮,点击后删除当前元素。
初始代码如下:
父组件:

<template>
    <div class="content-body">
        <div>任务</div>
          <div>
            <ul>
              <li v-for="(item,index) in selectionConditionList" :key="index" style="margin:10px 0">
                <v-selection-condition-list></v-selection-condition-list> <button @click="deleteSelectionCondition(index)">删除</button>
              </li>
            </ul>
          </div>
          <div>
             <button @click="addNewSelectionTask">新建任务</button>
          </div>
    </div>
</template>

<script>
import vSelectionConditionList from './SelectionConditionList'
  export default
  {
    data()
    {
      return {
        selectionConditionList:[],
      }
    },
    methods: {
      // 添加新的用户筛选条件
      addNewSelectionTask(){
        this.selectionConditionList.push({});
      },
      // 删除用户筛选条件
      deleteSelectionCondition(index){
        console.log("delete.."+index);
        this.selectionConditionList.splice(index,1);
      }
    },
    components:{
      vSelectionConditionList
    }
  }
</script>
<style>
  .div_center {
    text-align: center;;
    width:100%;
    margin:0 auto;
  }
</style>

子组件:

<template>
  <input type="text" :value="inputName">
</template>

<script>
  export default
  {
    data()
    {
      return {
        inputName: Math.random()
      }
    },
    methods: {
    }
  }
</script>

出现的问题

运行代码后,点击新建任务,出现的结果如下图:
Vue项目中v-for数组删除第n项元素产生渲染错误问题及解决方法

点击第一行的删除按钮,预期当然是删掉第一行。然而出现的结果却是最后一行被删掉了,而其他元素未变。删除中间某元素也是最后一行被删掉。这时通过console控制台的打印输出可以看到,删除的index索引是正确的。本人是vue新手,遇到此问题有些懵,查询官方文档及百度相关问题无果后,在segmentfault问答区提问,当时问题链接。然鹅提问一天以后,收到的回答还是没有完全解决问题,于是继续寻求解决方案。

解决方法

经过再次苦苦查询相关问题的问答帖及文章,终于发现问题是出在v-for的:key上。关于v-for中的:key介绍参见此页面:Vue2.0 v-for 中 :key 到底有什么用?,内容一大堆balabala,总之是由于虚拟DOM的原因引起的,我的理解就是:表单列表的生成是通过绑定的selectionConditionList数组来生成的,当selectionConditionList删除掉一项时,表单列表的dom对象自然也会减少一项。但是由于v-for循环的是子组件,子组件内部显示数据并未绑定selectionConditionList数组里的属性,因此子组件的显示数据并未按新数组重新渲染,体现出来的结果就是最后一个元素被删掉了。
解决方法就是给:key赋予一个独一无二的值,这样绑定的数组就可以和dom对象一一对应起来,删除的时候也能正确删除掉响应dom对象了。绑定这个“独一无二”的值,其中一个方法就是使用guid,也就是Global Unique Identifier,于是把生成guid的方法写到了一个公共的js文件里,:key绑定guid值,测试ok,大功告成!
代码如下:
父组件:

<template>
    <div class="content-body">
        <div>任务</div>
          <div>
            <ul>
              <li v-for="(item,index) in selectionConditionList" :key="item.guid" style="margin:10px 0">
                <v-selection-condition-list></v-selection-condition-list> <button @click="deleteSelectionCondition(index)">删除</button>
              </li>
            </ul>
          </div>
          <div>
             <button @click="addNewSelectionTask">新建任务</button>
          </div>
    </div>
</template>

<script>
import Utils from '../utils/utils.js'
import vSelectionConditionList from './SelectionConditionList'
  export default
  {
    data()
    {
      return {
        selectionConditionList:[],
      }
    },
    methods: {
      // 添加新的用户筛选条件
      addNewSelectionTask(){
        this.selectionConditionList.push({guid:Utils.guid()});
      },
      // 删除用户筛选条件
      deleteSelectionCondition(index){
        console.log("delete.."+index);
        this.selectionConditionList.splice(index,1);
      }
    },
    components:{
      vSelectionConditionList
    }
  }
</script>
<style>
  .div_center {
    text-align: center;;
    width:100%;
    margin:0 auto;
  }
</style>

子组件:

<template>
  <input type="text" :value="inputName">
</template>

<script>
  export default
  {
    data()
    {
      return {
        inputName: Math.random()
      }
    },
    methods: {
    }
  }
</script>

guid方法:

const utils = {
  guid: function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random() * 16 | 0,
        v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  }
}
export default utils

后话

此问题只出现在v-for嵌套子组件的情况下。如果是v-for循环一个div或表单对象,而对象中的数据都是通过数组中的对象属性绑定的,那么数组删除其中一项后,dom对象列表也可以相应正确渲染。有兴趣的话可以把子组件换成input对象,然后在selectionConditionList中添加类似{val:Math.random()}这样的数据,实测删除后是没有问题的。

点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
橘子橙 橘子橙
4年前
vue-element-admin项目打包后,iconfont图标出现乱码
使用vueelementadmin或者vueelementtemplate开发的项目,打包到线上,就出现了图标乱码,f12后能看到icon元素为.eliconclose:before{content:"□"}的情况(如下)
Wesley13 Wesley13
4年前
java List 数组删除元素
在java中,ArrayList是一个很常用的类,在编程中经常要对ArrayList进行增、删、改、查操作。之前在学校时一直认为删除操作是最简单的,现在才越发觉得自己愚蠢。只需要设置好预期条件的查询才是最简单的,删除涉及到存储空间的释放,以及数组的遍历等问题,在list的操作中相对还算小老哥呢。这两天在给小程序提供后台接口,因为设计的改变,需要
Jacquelyn38 Jacquelyn38
4年前
关于Vue在面试中常常被提到的几点
❝现在Vue几乎公司里都用,所以掌握Vue至关重要,这里我总结了几点,希望对大家有用❞1、Vue项目中为什么要在列表组件中写key,作用是什么?我们在业务组件中,会经常使用循环列表,当时用vfor命令时,会在后面写上:key,那么为什么建议写呢?key的作用是更新组件时判断两个节点是否相同。相同则复用,不相同就删除旧的创建新的。正是因为带唯一key时
Jacquelyn38 Jacquelyn38
4年前
手把手教你实现一个Vue无限级联树形表格(增删改)
前言平时我们可能在做项目时,会遇到一个业务逻辑。实现一个无限级联树形表格,什么叫做无限级联树形表格呢?就是下图所展示的内容,有一个祖元素,然后下面可能有很多子孙元素,你可以实现添加、编辑、删除这样几个功能。资源JavaScript框架:vue.jsUI框架:ElementUI源码这里需要重点说明的是,主要使用了递归的算法以及给数
Stella981 Stella981
4年前
Python+Selenium自动化篇
本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子。0.元素定位方法主要有:id定位:find\_element\_by\_id('')name定位:find\_element\_by\_name('')class定位:find\_element\_by\_class\_name(''
Stella981 Stella981
4年前
Leetcode 703. 数据流中的第K大元素
1.题目要求设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。你的KthLargest 类需要一个同时接收整数 k和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用KthLargest.add,返回当前数据流中第K大的元素。示例:
Stella981 Stella981
4年前
PHP中unset,array_splice删除数组中元素的区别
php(https://www.oschina.net/p/php)中删除数组元素是非常的简单的,但有时删除数组需要对索引进行一些排序要求我们会使用到相关的函数,这里我们来介绍使用unset,array\_splice删除数组中的元素区别吧如果要在某个数组中删除一个元素,可以直接用的unset,但是数组的索引不会重排:?(https://ww
Wesley13 Wesley13
4年前
Java中ArrayList的使用
ArrayList类是一个特殊的数组动态数组。来自于System.Collections命名空间;通过添加和删除元素,就可以动态改变数组的长度。优点:1、支持自动改变大小2、可以灵活的插入元素3、可以灵活的删除元素局限:比一般的数组的速度慢一些;用法一、初始化:1、不初始化容量ArrayList
Wesley13 Wesley13
4年前
Java删除List元素的方法
一、正序删正序删,如果只删除至多1个元素,那只需要在删除后使用break语句跳出循环即可,如果需要删除多个元素,若不注意控制当前列表的size和下一个元素的index,容易报_java.lang.IndexOutOfBoundsException_异常publicstaticvoidremove(List<Stringlis
上海张律师 上海张律师
8个月前
bindsheet+键盘在页面跳转时的bug及处理思路
​HarmonyOS应用开发最近做的一个项目中,有这样的一个需求在A页面中,点击某一项目后,会弹出一个bindsheet,同时,会给TextInput组件自动加上焦点,目的是为了弹出输入框,图片如下:当用户输入了金额数字后,点击“去计算”按钮,则通过rou
数据治
数据治
Lv1
坐观垂钓者,徒有羡鱼情。
文章
4
粉丝
0
获赞
0