Vue学习之watch监听器详解

Watch监听器详解

疫情期间在家蹲得都变懒咯,有短时间没写博客啦这次萌芽跟大家来谈谈Vue中的watch监听器!周末有小伙伴跟萌芽提到“深度监听”这个词,我寻思着不就是watch吗?怎么还分深的浅的?后来查了下才发现是萌芽小白了。
watch基本上可以分为三种模式:【浅监听【深监听】【局部监听】
这里萌芽先讲一下watch监听器是什么以及使用方式。[官方对watch的解释]

  • 观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代。
  • 一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。

浅监听

平常我们直接在watch里面写监听函数就是浅监听,就像我上面给出的例子,只有在监听对象发生改变才会执行监听函数。

    var vm = new Vue({
        data: { a: 1 },
        watch: {
            a (val, oldVal) {
                console.log('新的: %s, 旧的: %s', val, oldVal)
            },
        }
    })
    vm.a++;

但是,如果a是个对象的话那么他就无法监听到!下面的代码执行后他并没有监听到内容,但是 a 的属性值确实改变了!如果你想让监听器有反应除非你将整个 a 重新赋值也就是说 浅监听无法监听到他内部属性值的改变 

 var vm = new Vue({
        data: {
            a: {
                apple: '',
                num: 1,
            }
        },
        watch: {
            a(val, oldVal) {
                console.log('监听器触发')
            },
        }
    })
    vm.a.num++;
    vm.a.apple = '苹果';

 深监听

我们可以看到比起浅监听,深监听多了两个新东西:

  • handler:该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深。
  • deep:为了发现对象内部值的变化,可以在选项参数中指定 deep: true 。注意监听数组的变动不需要这么做。

deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler。                       - 摘自 监听对象的一些深入研究

    var vm = new Vue({
        data: {
            a: {
                apple: '',
                num: 1,
            }
        },
        watch: {
            a: {
                handler: function (val, oldVal) {
                    console.log('监听器触发')
                },
                deep: true
            },
        }
    })
    vm.a.num++;
    vm.a.apple = '苹果';

知识扩充:说起deep其实CSS中有一个【 /deep/ 深度选择器】,好用的一批这里不详谈了感兴趣可以搜下。

局部监听

正如刚刚说的所有属性都加上监听器的话性能不是很好,而且我们实战项目中往往也用不到监听所有的属性。怎么办呢?这个时候我们可以使用【局部对象属性监听】!萌芽觉得这么叫比较局部监听省事。我们可以发现文档里其实已经给出了解决方案:

    var vm = new Vue({
        data: {
            a: {
                apple: '',
                num: 1,
                fruits: {
                    banana: true,
                    orange: true,
                    peach: true,
                }
            }
        },
        watch: {
            'a.apple'(val, oldVal) {
                console.log('监听器触发')
            },
            'a.fruits': {
                handler(val, oldVal) {
                    console.log('监听器触发')
                },
                deep: true
            }
        }
    })

我们可以看到这样就既可以根据项目情况选择性的去监听内容啦,性能也很好,可以说是非常的完美了~
但是这个时候萌芽又有疑问了,如果我想让他一开始就执行监听函数怎么办呢?往下看!

immediate

  • immediate: true 将在创建完毕立即触发回调函数。设置了这个我们就可以完美解决刚刚的问题咯。

小伙伴说这个不够详细萌芽来补充一下,简单来讲就是说初始化完毕立刻触发一次这个函数。那么问题来了,监听器和created哪个先执行?答案是监听器!因为执行到created的时候data和methods已经创建了好了所以这个时候的监听器也是创建好了的!在监听器创建好的时候因为设置了immediate他会立刻执行一次

   var vm = new Vue({
        data: { a: 1 },
        watch: {
            a: {
                handler(val, oldVal) {
                    console.log('新的: %s, 旧的: %s', val, oldVal)
                },  //这个新的旧的萌芽之前的说法容易让人误解萌芽再解释一下,新的代表【当前】的,旧的代表【之前】的
                immediate: true
            },
        }
    })
    // vm.a++;  这里萌芽注视掉了,但是监听器里的内容还是会触发一次

注销监听

有种说法是:当watch没用的时候我们应该注销掉原来页面的 watch 的,不然的话可能会导致内置溢出,萌芽没深究过不过我们平常写在组件里的不用担心这个问题,因为组建里的东西都会随着组件销毁而销毁。如果不是组件里的话官方也给出了销毁方式。我们可以通过这种形式来手动注销掉监听器,vm.$watch 返回一个取消观察函数,用来停止触发回调:

var unwatch = vm.$watch('a', cb)
unwatch()  // 之后取消观察

踩坑时间


注意事项:https://cn.vuejs.org/v2/guide/list.html#注意事项

官方文档:

https://cn.vuejs.org/v2/api/#watch
https://cn.vuejs.org/v2/api/#vm-watch

发布了46 篇原创文章 · 获赞 43 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Meng_ya_zi/article/details/104768066