Vue踩坑实录:数组下标修改数据,页面死活不更新

最近在写一个简单的列表修改功能时,被一个小bug卡了快半小时,明明逻辑看着没问题,控制台打印也正常,页面就是不更新。现在把完整踩坑过程记录下来,也给自己提个醒。

我的需求很简单:页面展示一个数组列表,点击按钮修改列表第一项的值,视图同步更新。

按照原生JS的习惯,我直接写下标修改,代码如下:

<template>
  <div class="container">
    <h3>数组列表</h3>
    <div class="item" v-for="(item, index) in numList" :key="index">
      {{ item }}
    </div>
    <button @click="changeFirst">修改第一项</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      numList: [11, 22, 33, 44]
    }
  },
  methods: {
    changeFirst() {
      this.numList[0] = 999
      
      console.log("修改后的数组:", this.numList)
    }
  }
}
</script>

<style scoped>
.container {
  padding: 20px;
}
.item {
  margin: 10px 0;
  font-size: 16px;
}
button {
  padding: 8px 16px;
  cursor: pointer;
}
</style>

写完我直接运行,点下按钮,结果人傻了:
控制台清清楚楚输出:修改后的数组:[999, 22, 33, 44]
但页面上,第一项依旧是 11,一动不动。

我的排查心路历程(真实踩坑过程)

看到这个现象我第一反应是:事件没绑定上?

• 重新检查 click 事件名,没错。

• 加了 console 发现事件确实触发了,数据也确实变了。

然后怀疑:是不是 key 重复导致渲染问题?

• 把 index 改成唯一 id,依旧不更新。

又怀疑:是不是被 CSS 隐藏了?

• 打开控制台看元素,内容还是旧的。

当时甚至一度怀疑是 Vue 出bug了,或者热更新坏了,反复重启项目、清缓存,结果还是一样。

后来实在没办法,去翻之前的笔记,才猛然想起:
Vue 不能检测通过数组下标直接修改的数据变化!

瞬间恍然大悟,刚才一顿操作全是无用功,根本方向就错了。

在这里插入图片描述

原因说明

Vue2 的响应式是基于 Object.defineProperty 实现的,它能监听对象的读写,但无法监听数组下标赋值和数组长度修改
Vue 只对数组的这些方法做了响应式处理:

push、pop、shift、unshift、splice、sort、reverse

直接写 arr[index] = xxx 不会触发劫持,所以数据变了,视图不更新。

正确的几种写法

1. 使用 this.$set(推荐)

changeFirst() {
  this.$set(this.numList, 0, 999)
}

2. 使用 splice

changeFirst() {
  this.numList.splice(0, 1, 999)
}

3. 直接替换新数组

changeFirst() {
  this.numList = [999, 22, 33, 44]
}

改完之后,页面立刻正常更新,问题解决。

总结

以后再遇到这种情况:

• 数据在控制台正常更新

• 页面不渲染

• 控制台不报错

• 代码逻辑看起来没问题

优先排查是不是:

• 直接用下标改数组

• 给对象新增了属性没有用 $set

• 修改了数组长度

这都是Vue最经典的响应式坑,新手几乎必踩,我也算又加深了一遍印象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值