首页 > 其他分享 >Vue-watch-deep 深度监听

Vue-watch-deep 深度监听

时间:2023-06-13 18:25:46浏览次数:33  
标签:Vue watch deep newValue numbers 监听 属性

首先明确一个概念,Vue 是可以监听到 多层级数据改变的,且可以在页面上做出对应展示。但是 Vue 提供的 watch 方法,默认是不提供 深度监听的( deep 默认为 false,也就是不开启深度监听)

(刚挂载的时候是不执行的,只有挂载完成之后的变化才会执行。如果我们想要初次挂载的时候就l执行,则需要:immediate:true),

handler:watch的语法中是一直有这个handler方法的,只是没有添加immediate和deep属性的时候可以省略。

--------------------------------举例:deep

这是例子的html 片段:点击对应按钮之后,a 或 b 分别自增1

<div id="root">
{{numbers.a}}
<button @click='numbers.a++'>a++</button>
<br><br><br>
{{numbers.b}}
<button @click='numbers.b++'>b++</button>
</div>
1、监听对象内部属性变化:当我只改变a的时候,只监听a的变化


<script>
const vm = new Vue({
el: '#root',
data() {
return {
numbers: {
a: 1,
b: 1
}
}
},
watch: {
a: {
handler(newValue, oldValue) {
console.log(newValue, oldValue)
console.log('numbers正在被侦听')
},
// deep: true,
// immediate: true
}
}
})

</script>

 

点击按钮,发现 a 是新增了,但是控制台上没有输出,这就表明了,此时 a 是没有被监听到的。那么,当我开启 deep 之后是什么情况呢?实验证明,开启之后,a还是未被监听到的,这就表示了,此时监听 a 是监听不到的。

由此得出:当存在多层属性嵌套时,直接监听内层属性时无法做到的。因为此时vm上存在的只有data内的一级属性,外加计算属性,data内层属性是 observe 取的

2、监听对象内部属性变化:当我只改变a值的时候,通过最外层的属性,监听到内部改变的属性

watch: {
'numbers.a': {
handler(newValue, oldValue) {
console.log(newValue, oldValue)
console.log('numbers正在被侦听')
},
deep: true,
// immediate: true
}
}
在这里,通过最外层的 numbers 属性,来访问到内部的 改变的 a属性,然后监听 numbers.a,此时,我们发现,无论是否开启 deep:true ,只要改变了a的值,都会触发监听动作。但是改变了b之后,是不会触发监听动作的

 

结论:可以通过 外层属性访问内层属性的结构,来监听内层属性

 

3、监听整个 numbers 中 每个属性的变化

按照监听 a 属性的写法,如果我们要监听 整个 numbers 属性,那我们可以直接把 监听 属性a 的代码复制一份,然后把监听对象改成b就行

watch: {
'numbers.a': {
handler(newValue, oldValue) {
console.log(newValue, oldValue)
console.log('numbers.a正在被侦听')
},
},
'numbers.b': {
handler(newValue, oldValue) {
console.log(newValue, oldValue)
console.log('numbers.b正在被侦听')
},
}
}

事实证明这样是可行的,但是如果我的 numbers 内部,存在数以百计的属性,那么我需要怎么监听整个 numbers 的改变?总不能每个属性都单独写一个监听的动作吧,那代码该有多少重复的?所以监听整个 numbers 肯定是有别的方法的。

 

4、直接监听整个 numbers 属性的变化

watch: {
numbers: {
handler(newValue, oldValue) {
console.log(newValue, oldValue)
console.log('numbers正在被侦听')
},
},
}
从结果可以看出,即使 numbers 内部的 a、b 都已经改变了,但是并未监听到 numbers 的改变。

 

这是因为,这样写的话,numbers 是 data 中的key,那 value 则是numbers的内存地址。 vue 监视的是 numbers ,也就是说,vue 此时监视的是 numbers 对象属性的 内存地址,只要内存地址不改变,则不会监听 numbers 的改变,即使改变了 numbers 内部的属性值,但是 numbers 对应的内存地址,所以这样写的时候 vue 是不会监视 numbers 内部的属性。

如果,我直接改变了 numbers 的内存地址,那么vue就会执行监听动作,下面的代码就是证明

<button @click='numbers = {a:"qqq",b:"www"}'>b++</button>

const vm = new Vue({
el: '#root',
data() {
return {
numbers: {
a: 1,
b: 1
}
}
},
watch: {
numbers: {
handler(newValue, oldValue) {
console.log(newValue, oldValue)
console.log('numbers正在被侦听')
},
},
}
})

点击按钮之后,直接改变了整个 numbers,这样就在内存中重新开辟了一块,numbers 也就指向了一个新的地址,那么vue就执行了监听动作,控制台输出了监听参数

 

 

但是我们需要的肯定不是这样,我们需要的是,在内存地址不改变的情况下,改变 numbers 内部的属性,此时 vue 也能监听到 内部属性的改变。

deep:true 开启深层属性监听,默认为 false 不监听

还是以上面的代码为例,配置 deep:true 之后,单独改变 numbers 内部的属性,看看能否监听到 numbers 内部属性的改变。

<div id="root">
{{numbers.a}}
<button @click='numbers.a++'>a++</button>
<br><br><br>
{{numbers.b}}
<button @click='numbers.b++'>b++</button>
</div>

<script>
Vue.config.productionTip = false

const vm = new Vue({
el: '#root',
data() {
return {
numbers: {
a: 1,
b: 1
}
}
},
watch: {
numbers: {
handler(newValue, oldValue) {
console.log(newValue, oldValue)
console.log('numbers正在被侦听')
},
deep: true
},
}
})
</script>

分别点击两个按钮,能看到两个属性都发生了改变,且控制台上输出了两次监听信息,这就说明了,配置 deep:true 之后,在改变内部属性之后,vue 也是能监听到的

 

 

通过实例改变多层级内部属性,vue能监听到

还是上面的例子,但是 不配置 deep:true,然后通过 vm 访问 numbers.a ,且改变 属性 a 的值,看看页面效果

 

 

可以看到,通过实例改变属性 a 的值之后,页面上也展示了新的数据,在这就证明了,vue 确实是能自动监听到 多层级的内部属性的改变的。但是 watch 内部监听的函数没有执行

当我开启 deep:true 之后,然后在改变 属性 a 的值,再来看看页面展示和控制台输出

 

 

这里可以看到,vue还是是能监听到内部属性的改变的,且一旦开启了 deep:true 之后,在 watch 中 监听的多级属性在 内部属性 改变之后,也能被 watch 监听到了。

本章小结

深度监视:

1、Vue实例默认会监听对象内部值的改变且页面上对应改变,但是Vue的watch(vm.$watch)默认不监听对象内部值的改变

2、配置deep:true,可以在 watch($watch) 中监听 对象内部的值的改变

备注:使用 watch 时,需要根据数据结构,判断是否采取深度监听(deep:true)

------------------------------handler

new Vue({
el: '#app',
data: {
num: 0,
sum:10,
},
watch: {
// 只要num的值发生变化,sum的值就会变化 不用handler的简洁写法
num(newValue, oldValue) {
this.sum= newValue;
}
// 也可以使用handler方法写
num:{
handler(newValue, oldValue) {
this.sum = newValue;
}
}
}
})

转自:https://blog.csdn.net/qq_40792800/article/details/121102633,https://blog.csdn.net/weixin_44447255/article/details/122497792 --有修改

标签:Vue,watch,deep,newValue,numbers,监听,属性
From: https://www.cnblogs.com/Dasate/p/17478381.html

相关文章

  • NMI watchdog :BUG:softlockup 解决方案
    问题现象:解决方案:解决办法:设置为30s覆盖到配置文件中echo30>/proc/sys/kernel/watchdog_thresh查看tail-1/proc/sys/kernel/watchdog_thresh30临时生效sysctl-wkernel.watchdog_thresh=30常见原因:1>服务器电源供电不足,导致CPU电压不稳导致CPU死锁2>vcpus超过物理cpu实......
  • vue 的双向绑定原理(vue 的响应式原理)流程
    一、原理 二、流程第一步,“数据劫持”vue2.x用Object.defineProperty()方法来实现数据劫持,为每个属性分配一个订阅者集合的管理数组depvue3.x用ES6的Proxy构造函数来实现数据劫持。第二步,“添加订阅者”在编译的时候在该属性的数组dep中添加订阅者添加方......
  • vue3进阶——组件基础
    组件允许我们将UI划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构,这和我们嵌套HTML元素的方式类似,Vue实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。定义组件当使用构建步骤时,我们一般......
  • vue中computed的详细讲解
    1.定义    computed是vue的计算属性,是根据依赖关系进行缓存的计算,只有在它的相关依赖发生改变时才会进行更新2.用法    一般情况下,computed默认使用的是getter属性  3.computed的响应式依赖(缓存)1.computed的每一个计算属性都会被缓存起来,只要计......
  • Vue项目优化
    一、代码层面优化(1)v-if和v-show区分使用场景v-if和v-show的区别区别v-ifv-show手段动态的向DOM树内添加或者删除DOM元素通过设置DOM元素的display样式属性控制显隐编译过程有一个局部编译/卸载的过程是简单的基于css切换编译条件初始条件为假,则什么也不......
  • vue WebUploader 分片上传
    ​ 我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。这次项目的需求:支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,ie8,ie9,Chrome,Firefox,360安全浏览器,并且刷新浏览器后仍然能够续传,重启浏览器(关闭......
  • Vue SSR
    1、概念【SSR的本质就服务端返回渲染好的html文档】vue在客户端将标签渲染成的整个html片段的工作在服务端完成服务端形成的html片段直接返回给客户端这个过程就叫做服务端渲染2、优缺点(1)优点更好的SEO​在SPA中是抓取不到页面通过Ajax获取到的内容SSR是直......
  • vue2 学习提纲
    手册慕课网-vue2手册:http://www.imooc.com/wiki/vuelesson/vueslot.html视频vue2.5入门https://www.imooc.com/learn/980echarts数据报表https://coding.imooc.com/learn/list/499.htmlVue+EChart4.0从0到1打造商业级数据报表项目vue2.6的版本2.快速入......
  • vue中watch监听
    1.对data中一般数据的监听,使用watch,回调有newValue和oldValue两个参数,当数据变化后触发watch:{/***data中数据的监听*@paramnewValue*@paramoldValue*/value:function(newValue,oldValue){alert('监听'+oldValue+'变为'+ne......
  • vue2.0中使用element-ui时报错
    1、重新安装依赖a)  yarnaddbabel-preset-es2015--devb)  npminstallbabel-preset-es2015-D2、修改babel.config.js配置module.exports={ presets:['@vue/cli-plugin-babel/preset',['@babel/preset-env',{modules:false}]], ......