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

目录
  • 前言
  • 一:利用索引直接改变arr的值 如我在button事件中写的(arr[0]=1000)
  • 二:直接修改数组的长度 如this.arr.length=3
  • 总结如下

前言

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方法不能监听数组内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue.js使用watch监听路由变化的方法

    watch除了可以监听数据的变化,路由的变化也能被其监听到 效果如下: 具体代码 当路由发生变化后,在watch中写具体的业务逻辑 let vm = new Vue({ el: "#app", data: {}, router, watch: { '$route.path': function (newVal, oldVal) { if (newVal === '/login') { console.log('欢迎进入登录页面'); } if (newVal === '/registe

  • vue watch监听对象及对应值的变化详解

    如下所示: var vm=new Vue({ data:{ a:1, b:{ c:1 } }, watch:{ a(val, oldVal){//普通的watch监听 console.log("a: "+val, oldVal); }, b:{//深度监听,可监听到对象.数组的变化 handler(val, oldVal){ console.log("b.c: "+val.c, oldVal.c);//但是这两个值打印出来却都是一样的 }, deep:true }

  • 解决Vue2.0 watch对象属性变化监听不到的问题

    问题 很早之前就遇到一个问题,父组件向子组件传值,子组件监听传入对象的某个属性.发现子组件使用deep watch都不能观察到对象中属性的变化,今天终于找到为啥出现这种问题和解决办法了. 解决 为啥出现这种问题?受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除. 请参照https://v1-cn.vuejs.org/guide/reactivity.html 解决方式: 通过vue的this.$set(object, key, value)方法 通过Object.assign()

  • Vue数据监听方法watch的使用

    watch本身很容易理解, watch负责将视图中的数据与某个函数关联起来 当Vue视图中的数据变化时, 关联的函数会被执行 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>监听方法watch的使用</title> <script src="https://cdn.bootcss.com/

  • vue watch普通监听和深度监听实例详解(数组和对象)

    下面通过一段代码给大家介绍vue watch的普通监听和深度监听,具体代码如下所示: var vm=new Vue({ data:{ num:1, obj:{ name:'三儿', age:'21', sex:'女' } }, watch:{ num(val, oldVal){ //普通的watch监听 console.log("num: "+val, oldVal); }, obj:{ //深度监听,可监听到对象.数组的变化 handler(val, oldVal){ console

  • vue中的watch监听数据变化及watch中各属性的详解

    首先确认 watch是一个对象,一定要当成对象来用. 对象就有键,有值. 键:就是你要监控的那个家伙,比如说$route,这个就是要监控路由的变化.或者是data中的某个变量. 值可以是函数:就是当你监控的家伙变化时,需要执行的函数,这个函数有两个形参,第一个是当前值,第二个是变化后的值. 值也可以是函数名:不过这个函数名要用单引号来包裹. 第三种情况厉害了. 值是包括选项的对象:选项包括有三个. 1.第一个handler:其值是一个回调函数.即监听到变化时应该执行的函数. 2.第二个是deep

  • Vue使用watch监听一个对象中的属性的实现方法

    问题描述 Vue提供了一个watch方法可以让使用者去监听某些data内的数据变动,触发相应的方法,比如 queryData: { name: '', creator: '', selectedStatus: '', time: [], }, 第一种解决方案:直接对象 现在我需要监听这个queryData,我可以这样做: watch: { queryData: { handler: function() { //do something }, deep: true } } 第二种解决方案:dee

  • 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 子组件watch监听不到prop的解决

    问题描述 在vue项目中,父组件通过prop给子组件传值时,如果prop值是从服务器端获取,则父组件可能会传给子组件一个默认值(服务端数据还未及时获取),那么,我们就需要实时watch这个prop值,一旦prop值有更新,将立即通知子组件更新. 解决方案 watch: { levelDetail: { immediate: true, // 很重要!!! handler (val) { this.levelPersonal = !val ? {} : val // console.log('ac

  • Vuejs中的watch实例详解(监听者)

    最近刚刚追完庆余年,心思还总是在剧情里,然后就觉得在vuejs里watch就是监察院,一个不折不扣的特务机构.在Vue中watch被称为监听者,它随时观察这vue实例中每一个数据的变化,当数据发生改变,做出响应. 通过下面的示例代码来看一下这个监察院是怎么运作的: new Vue({ el:"#app", data(){ reutrn { candy:"" } }, //传说中的监察院start watch:{ candy:{ handler(newVal,oldV

随机推荐