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

 更新时间:2022年04月01日 10:10:19   作者:星海拾遗  
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性,下面这篇文章主要给大家介绍了关于Vue踩坑之Vue Watch方法不能监听到数组或对象值的改变的相关资料,需要的朋友可以参考下

前言

Vue不能监听到数组和对象值的变化其实和双向绑定的原理有关。Vue双向绑定原理是利用js中的Object.defineproperty重定义对象的GET和SET方法,而同时这种方法存在着缺陷。就是只能监听到对象内已有的值。在监听对象中属性变化的方法中中,无疑是 使用ES6的proxy更为优越。

同时我对Vue中不能监听到数组对象变化也做了试验。代码如下。

 let vm = new Vue({
        el: '#app',
        data: {
            message: 'wxs',
            arr:[1,2,3],
            obj:{
                name:'wxs',
                age:21
            }
        },
        methods:{
            change:function () {
                this.message = 'vue'
                this.arr[0]=100
                this.obj.name='xxx'
            }
        },
        watch:{
            message:function (newValue,oldValue) {
                console.log('message改变了')
            },
            arr:function (newValue,oldValue) {
                console.log('arr改变了')
            },
            obj:function (newValue,oldValue) {
                console.log('obj改变了')
            }
        },
        template: `<div><div>{{message}}</div><div>{{arr[0]}}</div><div>{{obj.name}}</div><button @click="change()">改变!</button></div>`
    })

很简单的代码,设置按钮改变message,arr,obj的值,同时对这三个值的变化设置监听事件,测试结果如下。

视图显示三个值都发生了改变,但是Vue只监听到了第一个值的改变。

官方文档给出如下解释

对此Vue提供了解决办法。

Vue不能监听到数组变化官方文档中提出有以下有两种情况。

一:利用索引直接改变arr的值 如我在button事件中写的(arr[0]=1000)

解决方法 将this.arr[0]=1000改写为Vue可以监听的形式 this.$set(this.arr,0,1000)

this.$set接受三个参数,第一个是需要操作的数组对象,第二个是需要修改的数据的数组下标,第三个是修改后的值。

上图看效果。

将修改arr值得方法修改如下

        methods:{
            change:function () {
                this.message = 'vue'
                this.$set(this.arr,0,100)
                this.obj.name='xxx'
            }
        },

成功监听

二:直接修改数组的长度 如this.arr.length=3 

来做个测试。我们用修改数组长度得方法删除数组中的值,看看watch能不能监听的到。

        methods:{
            change:function () {
                this.message = 'vue'
                this.arr.length=0
                this.obj.name='xxx'
            }
        },

结果,监听不到。

解决方法使用js中数组方法arr.splice操作数组达到修改长度的目的。

看看效果

        methods:{
            change:function () {
                this.message = 'vue'
                this.arr.splice(0,1)
                this.obj.name='xxx'
            }
        },

我们将数组的第一个值删除,此时数组的第二个值变成了arr[0],渲染到了页面中,watch监听成功。

Vue中无法监听对象属性的添加或者删除

解决方法:this.$set(obj,name,‘xxx’)对对象进行操作时,set接受三个参数,第一个为对象的名称,第二个为对象的key值,第三个为key对应的value值。

this.obj=Object.assign({},this.arr,{
age:21,
major:'soft'
})

这样操作之后,便可以成功监听到数组和对象的变化了

methods:{
            change:function () {
                this.message = 'vue'              
                this.$set(this.arr,1,100)
                this.$set(this.obj,'major','Vue')
            }
        },

控制台输出如下

那么问题来了,我改变的是对象的新值‘major’的值,请注意看我上面代码中method方法中的设置obj的代码。

此时Vue只是监听到了我改变了对象的新值。经过我测试,我改变对象的旧值,比如name值。Vue依然监听不到对象的变化。此时Vue提出了深度监听的方法如下。

但是这种方法经过我测试不能监听到对象新值的变化。

总结如下

总结:如果操作对象是数组,改变数组的值用Vue的$set方法,改变数组的长度用数组的splice方法使数组变化变成可监听的。如果操作对象是对象。如果操作的属性是对象内已经有的值,使用$watch,加上关键字deep深度监听对象,如果操作的属性是对象内没有的新属性。使用$set使对象变成可监听的!

到此这篇关于Vue踩坑之Vue Watch方法不能监听到数组或对象值的改变的文章就介绍到这了,更多相关Vue Watch方法不能监听数组内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue2升级vue3问题bug解决分析整理

    vue2升级vue3问题bug解决分析整理

    这篇文章主要介绍了vue2升级vue3遇到的问题bug解决分析整理,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 简单实现vue中的依赖收集与响应的方法

    简单实现vue中的依赖收集与响应的方法

    这篇文章主要介绍了简单实现vue中的依赖收集与响应的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-02-02
  • Vue-cli项目获取本地json文件数据的实例

    Vue-cli项目获取本地json文件数据的实例

    下面小编就为大家分享一篇Vue-cli项目获取本地json文件数据的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • Vue自定义指令简介和基本使用示例

    Vue自定义指令简介和基本使用示例

    同时Vue也支持让开发者,自己注册一些指令,这些指令被称为自定义指令,每个指令都有自己各自独立的功能,这篇文章主要介绍了Vue自定义指令简介和基本使用,需要的朋友可以参考
    2024-03-03
  • Vue生命周期与setup深入详解

    Vue生命周期与setup深入详解

    Vue的生命周期就是vue实例从创建到销毁的全过程,也就是new Vue() 开始就是vue生命周期的开始。Vue 实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 等⼀系列过程,称这是Vue的⽣命周期
    2022-09-09
  • vue组件之全局注册和局部注册方式

    vue组件之全局注册和局部注册方式

    这篇文章主要介绍了vue组件之全局注册和局部注册方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Vue中从template到jsx语法教程示例

    Vue中从template到jsx语法教程示例

    这篇文章主要为大家介绍了Vue中从template到jsx语法教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • vuex学习之Actions的用法详解

    vuex学习之Actions的用法详解

    本篇文章主要介绍了vuex学习之Actions的用法详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • vue2.0使用v-for循环制作多级嵌套菜单栏

    vue2.0使用v-for循环制作多级嵌套菜单栏

    这篇文章主要介绍了vue2.0制作多级嵌套菜单栏,主要使用v-for循环生成一个多级嵌套菜单栏,这个方法应用非常广泛,需要的朋友可以参考下
    2018-06-06
  • vue-cli3 设置端口号(81)无效的解决

    vue-cli3 设置端口号(81)无效的解决

    这篇文章主要介绍了vue-cli3 设置端口号(81)无效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02

最新评论