Vue2中无法监听数组和对象的某些变化问题

目录
  • 一、数组
    • 1. 不能监听的情况
    • 2. 替代做法
    • 3. 注意
  • 二、对象
    • 1. 不能监听的情况
    • 2. 替代做法
  • 三、分析 vue 2 无法监听数组和对象的这些变化的原因
    • 1. 对于数组
    • 2. 对象
  • 四、vue 3响应式原理
  • 关于vue监听的一些问题
    • 对象的监听
    • 数组的监听

一、数组

1. 不能监听的情况

(1) 直接通过下标赋值  arr[i] = value

(2) 直接修改数组长度 arr.length = newLen

2. 替代做法

(1)修改值

Vue.set(arr, index, newvalue)
vm.$set(arr, index, newvalue)
arr.splice(index, 1, newvalue)

(2) 修改数组长度,

arr.splice(newLen)

3. 注意

调用数组的pop、push、shift、unshift、splice、sort、reverse等方法时是可以监听到数组的变化的

vue内部相当于重写了数组的原型,劫持了这七个方法

二、对象

1. 不能监听的情况

属性的新增和删除

obj.newkey=newvalue
delete obj.key

2. 替代做法

// 新增
 Vue.set(obj, newkey, newvalue)
 vm.$set(obj, newkey, newvalue)
 obj = Object.assign({}, obj, {newkey1: newvalue1, newkey2: newvalue2})
// 删除
 Vue.delete(obj, key)
 vm.$delete(obj, key)

三、分析 vue 2 无法监听数组和对象的这些变化的原因

首先,vue2是通过Object.defineProperty(obj, key, value)这种方式监听数据的

1. 对于数组

Object.defineProperty()是可以对数组实现监听操作的,但是vue并没有实现这个功能,因为数组长度不定而且数据可能会很多,如果对每一个数据都实现监听,性能代价太大

但是注意:数组中的元素是引用类型时是会被监听的

2. 对象

Object.defineProperty()针对的是对象的某个属性,而且这个操作在vue的初始化阶段就完成了,所以新增的属性无法监听,通过set方法新增对象就相当于初始化阶段的数据响应式处理

四、vue 3响应式原理

vue 3是通过proxy直接代理整个对象来实现的,而不是像Object.defineProperty针对某个属性。

所以,只需做一层代理就可以监听同级结构下的所有属性变化,包括新增属性和删除属性

关于vue监听的一些问题

对象的监听

vue通过object.defineProperty将对象的key转化成getter/setter的形式来追踪变化,但是这种追踪方式只能追踪到数据的修改,对象的属性的删除和增加,这种形式追踪不到。为此vue提供可$set 和$delete两种API来配合使用,解决监听不到属性新增删除问题。

*需要特别注意,在使用$set时,需要传递的参数有三个 vm.$set(target,key,value),target不能是Vue.js实例或者vue.js实例的根数据对象,所谓的根数据对象是指vm.$data *

*在使用$delete时候,也可以中另外一种方法实现,但是不太推荐:

 delete this.obj.name;
 this.obg._ob_.dep.notify  //手动向依赖发送变化通知;

(说明: _ob_ 是 vue中是否是响应式的判断依据)*

在使用$delete时候,target不能是Vue.js实例或者vue.js实例的根数据对象,

数组的监听

vue通过拦截数组原型的方式实现数组的变化的监听,所以有些不是数组原型定义的方法进行的数组操作,发生的变化,是数组感知不到的,比如通过数组下标修改对应位置的值(this.list[0] = 2),或者通过数组长度改变数组(比如通过数组length清空数组的操作: this.list.length = 0 )。

所以进行数组操作的时候,尽量使用数组原型方法操作:

push pop unshift shift concat reverse sort slice splice join 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Vue使用watch监听数组或对象

    1.普通的watch data() { return { frontPoints: 0 } }, watch: { frontPoints(newValue, oldValue) { console.log(newValue) } } 2.数组的watch data() { return { winChips: new Array(11).fill(0) } }, watch: { winChips: { handler(newValue, oldValue) { for (let i = 0;

  • vue中实现监听数组内部元素

    目录 vue监听数组内部元素 我们有两种办法解决此问题 vue如何监听数组的变化 vue监听数组内部元素 在VUE中,对数组的监听是浅监听,也就是它只能监听到数组的长度或者有无的变化,当我们修改数组中的某一个值时,也就是数组的长度状态并没有改变时,在正常情况下它是无法监听到的,在watch中我们知道可以使用deep属性进行深监听,那么在其他情况下呢? 我们有两种办法解决此问题 1.通过原生的js对数组先进行切割,然后在添加新的内容(也就是我们要修改的内容) array.splice(i, 1,

  • Vue踩坑之Vue Watch方法不能监听到数组或对象值的改变详解

    目录 前言 一:利用索引直接改变arr的值 如我在button事件中写的(arr[0]=1000) 二:直接修改数组的长度 如this.arr.length=3 总结如下 前言 Vue不能监听到数组和对象值的变化其实和双向绑定的原理有关.Vue双向绑定原理是利用js中的Object.defineproperty重定义对象的GET和SET方法,而同时这种方法存在着缺陷.就是只能监听到对象内已有的值.在监听对象中属性变化的方法中中,无疑是 使用ES6的proxy更为优越. 同时我对Vue中不能监听到

  • vue深度监听(监听对象和数组的改变)与立即执行监听实例

    1.vue中监听对象数据属性值的改变,可以使用深度监听 data () { return { form: { status: '', cpufrequency: '', systemstacksize: '', scalabilityclass: '' } } }, watch: { form: { // 深度监听 handler(val, oldVal){ console.log('currentForm',val, oldVal) // 但是这两个值打印出来却都是一样的,因为它们的引用指向同

  • vue中是怎样监听数组变化的

    我们知道通过Object.defineProperty()劫持数组为其设置getter和setter后,调用的数组的push.splice.pop等方法改变数组元素时并不会触发数组的setter,这就会造成使用上述方法改变数组后,页面上并不能及时体现这些变化,也就是数组数据变化不是响应式的(对上述不了解的可以参考这篇文章).但实际用vue开发时,对于响应式数组,使用push.splice.pop等方法改变数组时,页面会及时体现这种变化,那么vue中是如何实现的呢? 通过vue源码可以看出,vue

  • Vue2中无法监听数组和对象的某些变化问题

    目录 一.数组 1. 不能监听的情况 2. 替代做法 3. 注意 二.对象 1. 不能监听的情况 2. 替代做法 三.分析 vue 2 无法监听数组和对象的这些变化的原因 1. 对于数组 2. 对象 四.vue 3响应式原理 关于vue监听的一些问题 对象的监听 数组的监听 一.数组 1. 不能监听的情况 (1) 直接通过下标赋值  arr[i] = value (2) 直接修改数组长度 arr.length = newLen 2. 替代做法 (1)修改值 Vue.set(arr, index,

  • 关于vue中如何监听数组变化

    前言 前段时间学习了关于vue中响应式数据的原理,(并作了学习笔记vue响应式原理),其实是通过Object.defineProperty控制getter和setter,并利用观察者模式完成的响应式设计.那么数组有一系列的操作方法,这些方法并不会触发数组的getter和setter方法.那么vue中针对数组的响应式设计是如何实现的呢...那么我们一起去学习下吧~ 源码部分 https://github.com/vuejs/vue/blob/dev/src/core/observer/array.

  • Vue开发之watch监听数组、对象、变量操作分析

    本文实例讲述了Vue开发之watch监听数组.对象.变量操作.分享给大家供大家参考,具体如下: 1.普通的watch data() { return { frontPoints: 0 } }, watch: { frontPoints(newValue, oldValue) { console.log(newValue) } } 2.数组的watch:深拷贝 data() { return { winChips: new Array(11).fill(0) } }, watch: { winCh

  • 解决vue无法侦听数组及对象属性的变化问题

    一.数组 1.可以监听到的情况 如push.splice.=赋值(array=[1,2,3]) 2.无法监听到的情况 使用下标修改某个元素(这种比较常见) array[index] = 1 object.a = 3 直接修改数组length array.length = 5 3.解决方案 this.$set(array, index, data) - 这是个深度的修改,某些情况下可能导致你不希望的结果,因此最好还是慎用 this.dataArr = this.originArr this.$se

  • Vue监听数组变化源码解析

    上一篇的代码中,忽略了对数组的处理,只关心了需要关心的部分,假装数组不存在. 这一篇开始考虑数组的问题. 从最简单的入手 先考虑一个问题,如何监听数组中的对象变化?忽略掉数组本身及其中的一般值,只考虑对象数组中的对象. 遍历数组,而后对数组中的每个对象调用 observe 方法 // 上一篇中出现的未曾重写的代码,这一篇中不再重复 var Observer = function Observer(value) { this.value = value; this.dep = new Dep();

  • vue中watch监听不到变化的解决

    目录 watch监听不到对象内部的变化 解决方法: watch的handler方法的两个参数值相同 解决方法: 全部代码 watch监听不到对象内部的变化 有的时候vue会出现这种现象,无法监听到复杂对象内部的变化:当对象里面原本有某一个属性,并对这个属性操作时,watch是可以监听到当前属性的变化的.但是,若对象里面本没有这个属性的时候,在操作时将属性添加进去,同时包括之后对这个属性的操作,watch是都检测不到的.这是因为vue的watch会在初始化的时候通过object.definePro

随机推荐