vue2响应式修改数据(对象、数组)

Vue2不能检测对象属性的添加、删除
Vue2不能检测数组的项修改(添加,删除,修改)

解决方式
方式一

// $set是Vue.set的别名
this.$set(this.obj, k, v)
Vue.set(this.obj, k, v)
 
this.$delete(this.obj, k)
Vue.delete(this.obj, k)

方式二

//使用数组的操作函数(其实已被Vue进行了修改)
splice(),push(), pop(),shift(), unshift(),sort(), reverse()

整体代码测试案例

<template>
  <div class="home">
    <div>数组:{{ arr }}</div>
    <div>对象:{{ obj }}</div>
    <button @click="changeArr">点我更改数组(不会触发响应式)</button>
    <button @click="changeArr1">点我更改数组(会触发响应式)</button>
    <button @click="changeObj">点我删除对象(会触发响应式)</button>
    <button @click="changeObj1">点我新增对象(会触发响应式)</button>
  </div>
</template>

<script>
import Vue from "vue";
export default {
  data() {
    return {
      arr: [1, 2, 3, 4, 5],
      obj: {
        name: "张三",
        age: 19,
      },
    };
  },
  methods: {
    changeArr() {
      this.arr[0] = 234;
      // this.arr[this.arr.length] = 666;

      console.log(this.arr); //我们已经触发事件改变了 但是它页面没有响应式 所以我们用到了vue2的方法
    },
    changeArr1() {
      // this.arr.pop(); //使用数组方法触发响应式
      /*
      this.arr.splice(1, 1, 4);//第一个为起始,替换一个,替换值为4
      this.arr.reverse();//反转数组
      this.arr.shift();//前删
      this.arr.pop();//尾删
      this.arr.unshift(8);//前插元素
      this.arr.push(5);//尾部添加元素
      this.arr.sort();//从小到大排序
      */
      // this.$set(this.arr, 0, 234); //修改数组元素
      this.$set(this.arr, this.arr.length, 666); //新增数组元素
      // this.$delete(this.arr, 0);//删除数组元素是0的
      console.log(this.arr);
    },
    changeObj() {
      //对象的删除方法
      this.$delete(this.obj, "sex");
    },
    changeObj1() {
      //对象的新增方法
      this.$set(this.obj, "sex", "女");
      // this.obj.name = "男";
    },
  },
};
</script>

面试三连问
1、 为啥vue2的修改数组的索引不会触发响应式,但是修改对象的属性却可以触发响应式?
在JavaScript中,数组本质上是一种特殊类型的对象,其索引作为键。然而,当我们直接通过索引来修改数组元素,比如 arr[0] = ‘new value’,这个操作并没有触发JavaScript的常规属性访问器(getter和setter)。在非严格意义上讲,这是因为数组的索引访问并不是通过属性访问器实现的,而是语言规范中的一种特殊行为。
原理:Vue.js利用了Object.defineProperty方法来劫持(即拦截)对象属性的访问和修改,从而实现数据的响应式。这个方法允许你定义一个对象属性的getter(获取属性值时调用的函数)和setter(设置属性值时调用的函数)。当属性被访问或修改时,Vue可以通过这些getter和setter来追踪变化,并执行相应的更新操作。
但是,直接通过数组索引修改元素值的方式绕过了Vue设置的getter和setter,因为这不属于Object.defineProperty直接管理的属性访问方式。因此,Vue无法得知数组的这个变化,也就不会触发视图的更新。

2、为啥vue3就解决了这个问题?
Vue 3 解决了这个问题主要是因为它采用了不同的响应式机制——Proxy。相比于Vue 2中基于Object.defineProperty的响应式系统,Vue 3中的Proxy提供了更全面的陷阱(traps),可以拦截对象上几乎所有的访问和修改操作,包括数组索引的修改和长度的更改。
原理:Proxy 是ES6引入的一个新特性,它允许你创建一个对象的代理,用来“代理”对目标对象的各种操作。Proxy可以定义一组拦截器( traps),这些拦截器可以监听并控制目标对象上的各种访问和修改行为,比如get(获取属性值)、set(设置属性值)、has(检查属性是否存在)、deleteProperty(删除属性)等。
Vue 3 利用Proxy来创建一个代理,将数据包装起来。当数据被访问或修改时,Proxy的陷阱会被触发,Vue就可以在这个过程中记录变化、执行依赖更新逻辑等。由于Proxy是直接在对象层级进行拦截,无论是对象属性的添加、删除还是数组元素的修改,甚至是迭代器的使用,Vue 3 都能一一捕获到,因此极大地增强了响应式的灵活性和全面性。

3、那为啥vue2的对象删除不能触发响应式
Vue 2 使用 Object.defineProperty 在数据对象的每个响应式属性上设置 getter 和 setter。这些 getter/setter 能够在属性访问和修改时通知 Vue,触发视图更新。但是,当删除一个属性时,这个操作并不经过 getter 或 setter,因此 Vue 无法知道属性已被删除。
Vue 2 在实例初始化时会遍历 data 对象的所有属性,并将其转换为响应式的。这意味着只有在初始化阶段存在的属性才会被跟踪。如果在实例创建后动态添加或删除属性,Vue 的响应式系统默认是无法识别这些变化的。

  • 13
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值