浅谈 Vue2 数组对象新增属性,响应式失效问题

需求

在工作中我们可能有这样的需求,就是对数据进行改造,有时我们需要对原来的数据添加一些额外属性,以达到控制页面的效果。

需求如下(简单举例):

我们需要对页面进行点击,对点击到的数据进行变色,最后在提交的时候,我们需要把这些变色的数据提取出来,应该怎么做呢?

这个时候就需要对原始数据进行改造了,我们需要在原始的数据结构上面添加一个 checked 属性来标识是否进行点击或者选中,默认为 false,点击之后为 true,最后通过 filter 把 checked 为 true 的筛选出来即可,接下来演示一下。

ini 复制代码
    this.dataBack = [
      {
        value: '测试',
      },
      {
        value: '测试',
      },
    ]
    this.dataBack.forEach((item) => {
      item.checked = false
    })

可以看到,数据已经改造成功。

接下来我们拿到数据后就可以进行相关的点击操作了,下面是实现代码。

less 复制代码
  <div>
    <div v-for="(item, index) in dataBack" :key="index">
      <span
        :style="{
          color: item.checked ? 'red' : 'gray',
        }"
        @click="changeState(index)"
        >{{ item.value }}{{ item.checked }}</span
      >
    </div>
  </div>
javascript 复制代码
    changeState(index) {
      this.dataBack[index].checked = !this.dataBack[index].checked
      console.log(' this.dataBack: ', this.dataBack)
    },

我写了一个简单的样式,就是点击之后改变 span 的颜色,默认为 gray,点击之后为 red,按理说点击之后 index 对应的 checked 会取反,vue监听到 checked 为 true 时就会改变颜色,接下来看一下效果

就在我们觉得任务已经完成的时候,这个时候问题出现了!我先后点击了第一个和第二个,我们看到控制台的数据已经发生变化了,但是奇怪的是页面字体颜色和 checked 还是为 false,那么问题是什么呢?

原因

在给深层次的数据赋值或者给对象添加新的属性,页面上的数据并不会同步更新,这是因为 Vue 2不能检测到对象属性的添加或者删除,所以vue不允许在已经定义好的数据上动态的添加新的属性值。至于为什么,这里不做讲解,想了解的可以看下这篇文章blog.csdn.net/weixin_4344...

解决一

知道了原因,就好解决了,既然 Vue 不允许进行添加数据,或者说检测不到新增属性的变化,那么我们就不添加了,我们直接进行赋值,我们把处理好的数据直接丢给 Vue ,这样总行了吧?

javascript 复制代码
    let arr = [
      {
        value: '测试',
      },
      {
        value: '测试',
      },
    ]
    arr.forEach((item) => {
      item.checked = false
    })
    this.dataBack = arr
    console.log(' this.dataBack: ', this.dataBack)

我们使用变量去接收数据,对变量进行改造,然后将变量赋值给 Vue,这样 Vue 接收到的就是一个完整的数据了,我并没有对 Vue 直接进行添加属性,这下总可以监听到了吧?

果不其然,效果实现了。

解决二

使用 this.$set 进行赋值,也可以检测到变化,同样为响应式,这种写法也是常用的,不仅使用于这个场景,还适用于组件传值去修改深层次属性值,具体用法可以参考这篇文章。blog.csdn.net/lzfengquan/...

代码如下:

kotlin 复制代码
    this.dataBack = [
      {
        value: '测试',
      },
      {
        value: '测试',
      },
    ]
    this.dataBack.forEach((item) => {
      this.$set(item, 'checked', false)
    })

总结

当我们对 Vue 的深层次数据结构进行改造时,不可以直接对 Vue 数据进行添加属性,而是应该先对数据进行改造,然后将改造好的数据赋值给 Vue ,或者使用 this.$set 进行修改,这下 Vue 才可以检测到数据的变化,这也是在工作中经常使用的方法,希望可以帮助到大家,有什么写的不对的地方,大家也可以评论一起交流。

附上全部代码,大家可以自己试试。

xml 复制代码
<template>
  <div>
    <div v-for="(item, index) in dataBack" :key="index">
      <span
        :style="{
          color: item.checked ? 'red' : 'gray',
        }"
        @click="changeState(index)"
        >{{ item.value }}{{ item.checked }}</span
      >
    </div>
    <button @click="submit">提交</button>
  </div>
</template>
<script>
export default {
  name: 'DataTest',
  data() {
    return {
      dataBack: [],
    }
  },
  created() {
    //方案一
    let arr = [
      {
        value: '测试',
      },
      {
        value: '测试',
      },
    ]
    arr.forEach((item) => {
      item.checked = false
    })
    this.dataBack = arr

    //方案二
    // this.dataBack = [
    //   {
    //     value: '测试',
    //   },
    //   {
    //     value: '测试',
    //   },
    // ]
    // this.dataBack.forEach((item) => {
    //   this.$set(item, 'checked', false)
    // })
    console.log(' this.dataBack: ', this.dataBack)
  },
  methods: {
    changeState(index) {
      this.dataBack[index].checked = !this.dataBack[index].checked
      console.log(' this.dataBack: ', this.dataBack)
    },
    submit() {
      let data = this.dataBack.filter((item) => item.checked)
      console.log('data: ', data)
    },
  },
}
</script>

相关推荐
冻感糕人~3 分钟前
【珍藏必备】ReAct框架实战指南:从零开始构建AI智能体,让大模型学会思考与行动
java·前端·人工智能·react.js·大模型·就业·大模型学习
程序员agions7 分钟前
2026年,“配置工程师“终于死绝了
前端·程序人生
alice--小文子13 分钟前
cursor-mcp工具使用
java·服务器·前端
晚霞的不甘22 分钟前
揭秘 CANN 内存管理:如何让大模型在小设备上“轻装上阵”?
前端·数据库·经验分享·flutter·3d
小迷糊的学习记录31 分钟前
0.1 + 0.2 不等于 0.3
前端·javascript·面试
梦帮科技1 小时前
Node.js配置生成器CLI工具开发实战
前端·人工智能·windows·前端框架·node.js·json
VT.馒头2 小时前
【力扣】2695. 包装数组
前端·javascript·算法·leetcode·职场和发展·typescript
css趣多多2 小时前
一个UI内置组件el-scrollbar
前端·javascript·vue.js
C澒2 小时前
前端整洁架构(Clean Architecture)实战解析:从理论到 Todo 项目落地
前端·架构·系统架构·前端框架
C澒2 小时前
Remesh 框架详解:基于 CQRS 的前端领域驱动设计方案
前端·架构·前端框架·状态模式