第5集丨Vue 江湖 —— 监视属性/侦听属性

news/2024/12/28 13:03:58/

目录

  • 一、基本使用
    • 1.1 watch配置监视
    • 1.2 vm.$watch动态监视
    • 1.3 深度监视(deep watch)
    • 1.4 简写形式
  • 二、computed和watch的对比
    • 2.1 使用watch实现setTimeout操作
    • 2.2 用computed无法实现setTimeout
  • 三、其他注意事项
    • 3.1 vue devtools的bug
    • 3.2 @xxx=yyy格式
    • 3.3 将window传入data中

Vue 提供了一种更通用的方式来观察和响应 Vue实例上的数据变动:侦听属性,也成为监视属性

一、基本使用

监视属性watch:

  1. 当被监视的属性变化时,回调函数handler自动调用,进行相关操作。
  2. 监视的属性必须存在,才能进行监视。
  3. 监视的两种写法
    a. new Vue时传入watch配置
    b. 通过vm.$watch来动态实现监视

1.1 watch配置监视

下面案例中,我们通过watch配置属性来给isHuoguo 添加监视,当isHuoguo发生变化时,所配置的handler()函数会调用。

注意:这里有一个属性immediate,其默认值为false。当配置为true时,页面初始化时,让handler调用一下。

<div id="root"><h2>今天我们去吃{{info}}</h2><button @click="change">切换</button>
</div>
<script>const vm = new Vue({el:'#root',data:{isHuoguo:true},computed:{info() {return this.isHuoguo?'火锅':'南京大排档';}},methods: {change() {this.isHuoguo = !this.isHuoguo;}},watch: {isHuoguo:{immediate:true,//默认为false,初始化时,让handler调用一下。handler(newValue, oldValue) {console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);}}}})
</script>

效果图如下:

在这里插入图片描述

1.2 vm.$watch动态监视

不仅可以给属性(即data中定义的)添加监视,也可以给计算属性添加监视。

下面例子,我们通过vm.$watch 方式,来动态给计算属性info添加监视:

<div id="root"><h2>今天我们去吃{{info}}</h2><button @click="change">切换</button>
</div>
<script>const vm = new Vue({el:'#root',data:{isHuoguo:true},computed:{info() {return this.isHuoguo?'火锅':'南京大排档';}},methods: {change() {this.isHuoguo = !this.isHuoguo;}},watch: {isHuoguo:{// immediate:true,//默认为false,初始化时,让handler调用一下。handler(newValue, oldValue) {console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);}}}})// 监视计算属性vm.$watch('info',{// immediate:true,//默认为false,初始化时,让handler调用一下。handler(newValue, oldValue) {console.log("info计算属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);}})</script>

在这里插入图片描述

1.3 深度监视(deep watch)

深度监视(deep watch):

  1. Vue中的watch默认不监测对象内部值的改变(只监测一层结构)
  2. 配置deep:true可以监测对象内部值的改变(可以监测多层结构),Vue默认不开启deep,是为了提供效率。
  3. Vue自身可以监测对象内部值的改变,但是Vue提供的watch默认不可以。
  4. 使用watch时,要根据数据的具体结构,决定是否采用深度监视。

使用方式:

  • 监视多级结构中某个属性的变化,例如下面例子中numbers.a
  • 监视多级结构中所有属性的变化,numbers:{deep:true,handler(){}}
<div id="root"><h3>今天我们去吃{{info}}</h3><button @click="change">切换</button><hr><h3>a的值是{{numbers.a}}</h3><button @click="numbers.a++">点击a++</button><hr><h3>b的值是{{numbers.b}}</h3><button @click="numbers.b++">点击b++</button>
</div>
<script>const vm = new Vue({el:'#root',data:{isHuoguo:true,numbers:{a:1,b:1}},computed:{info() {return this.isHuoguo?'火锅':'南京大排档';}},methods: {change() {this.isHuoguo = !this.isHuoguo;}},watch: {isHuoguo:{handler(newValue, oldValue) {console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);}},// 监视多级结构中某个属性的变化"numbers.a": {handler() {console.log("a被改变了!");}},// 监视多级结构中所有属性的变化numbers:{deep:true,handler() {console.log("numbers改变了!");}}}})</script>

1.4 简写形式

当所配置的监视,只需要handler,不需要其他配置的时候,才可以使用简写形式,使用函数来代替。

两类简写形式:

  • watch配置里的简写
  • 动态添加监视的简写
<div id="root"><h3>今天我们去吃{{info}}</h3><button @click="change">切换</button>
</div>
<script>const vm = new Vue({el:'#root',data:{isHuoguo:true},computed:{info() {return this.isHuoguo?'火锅':'南京大排档';}},methods: {change() {this.isHuoguo = !this.isHuoguo;}},watch: {/* isHuoguo:{deep:true,immediate:true,handler(newValue, oldValue) {console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);}}, */// 简写形式isHuoguo(newValue, oldValue) {console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);}}})// 动态添加监视的简写vm.$watch('isHuoguo',function(newValue, oldValue){console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);})</script>

二、computed和watch的对比

计算属性(computed)和监视属性(watch)之间的区别:

  1. computed能完成的功能,watch都可以完成
  2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

两个重要的原则
3. 被Vue所管理的函数,最好写成普通函数,这样this的指向才是vm组件实例对象
4. 所有不被Vue管理的函数(定时器的回调函数(setTimeout)、ajax的回调函数、Promise的回调函数等),最好写成箭头函数,这样this的指向才是 vm组件实例对象

2.1 使用watch实现setTimeout操作

下面代码,使用了watch实现setTimeout操作,有一点需要注意的是,setTimeout所指定的回调函数要使用箭头函数(因为箭头函数本身没有this),否则this指向window了,而不再是vm实例。

<div id="root"><div class="row">姓:<input type="text" v-model="firstName"></div><div class="row">名:<input type="text" v-model="lastName"></div><div class="row">全名:<span>{{fullName}}</span></div>
</div><script>const vm = new Vue({el:'#root',data() {return {firstName: '小',lastName: '三',fullName:'小-三'};},methods:{},watch:{firstName(val) {setTimeout(() => {  //这里不能写成普通函数,否则this指向window了console.log(this);  //vm实例对象this.fullName = val + "-" + this.lastName;}, 1000);},lastName(val){this.fullName = this.firstName + "-" + val;}}});
</script>

2.2 用computed无法实现setTimeout

computed计算属性,无法实现setTimeout想要的功能,如下错误代码所示:

<div id="root"><div class="row">姓:<input type="text" v-model="firstName"></div><div class="row">名:<input type="text" v-model="lastName"></div><div class="row">全名:<span>{{fullName}}</span></div></div><script>const vm = new Vue({el:'#root',// 对于Vue来说,data中配置的就是属性。// 计算属性:用现有的属性去加工、计算生成一个全新的属性。和属性分开放data:{firstName: '小',lastName: '三'},computed:{fullName() {console.log('get被调用了!');// console.log(this);setTimeout(() => {return this.firstName+'-'+this.lastName}, 1000);}}});
</script>

三、其他注意事项

3.1 vue devtools的bug

当页面上没有用到某个计算属性时,vue devtools调试工具会出现一个bug:不会显示数据的变化了。例如下面代码

<div id="root"><h2>今天我们去吃米饭</h2><button @click="change">切换</button>
</div>
<script>const vm = new Vue({el:'#root',data:{isHuoguo:true},computed:{info() {return this.isHuoguo?'火锅':'南京大排档';}},methods: {change() {this.isHuoguo = !this.isHuoguo;}},})
</script>

点击切换按钮,工具中显示的datacomputed 不发生变化,其实数据已经发生了改变。可以通过控制台中输入vm.info来查看。如下图所示:

在这里插入图片描述
在这里插入图片描述

3.2 @xxx=yyy格式

这里的yyy不是事件名称,而是一些简单的语句。例如:@click="isHuoguo = !isHuoguo;count++;"

下面的案例中,两个按钮均可实现功能。不过需要注意的是,执行语句比较复杂的时候不建议直接写在yyy中。

<div id="root"><h2>今天我们去吃{{info}}--切换次数{{count}}</h2><button @click="change">切换</button><button @click="isHuoguo = !isHuoguo;count++">切换2</button>
</div>
<script>const vm = new Vue({el:'#root',data:{isHuoguo:true,count:0,},computed:{info() {return this.isHuoguo?'火锅':'南京大排档';}},methods: {change() {this.count++;this.isHuoguo = !this.isHuoguo;}},})
</script>

3.3 将window传入data中

window传入data中,实现alert弹框。如下代码所示:

<div id="root"><h2>今天我们去吃{{info}}--切换次数{{count}}</h2><button @click="change">切换</button><button @click="isHuoguo = !isHuoguo;count++">切换2</button><button @click="window.alert(1)">弹出alert</button>
</div>
<script>const vm = new Vue({el:'#root',data:{isHuoguo:true,count:0,window      //相当于window:window},computed:{info() {return this.isHuoguo?'火锅':'南京大排档';}},methods: {change() {this.count++;this.isHuoguo = !this.isHuoguo;}},})
</script>

http://www.ppmy.cn/news/1009128.html

相关文章

python性能调试

py-spy生成cpu火焰图 ft5.svg env/xxxx/bin pid26443$env/py-spy record -o /tmp/$f --pid $pid --nativememray实时查看内存 env/xxxx/bin$env/python -m memray run --live --trace-python-allocators --native run_demo.pymemray生成内存火焰图报告 frun_demo_042.bin en…

【数学】这可能是全网最容易的贝叶斯公式讲解

背景 上午在B站连续刷到两个讲贝叶斯的视频&#xff0c;都讲的极好&#xff0c;而且一个视频是从应用的角度&#xff0c;一个是从原理的角度。我将两个视频反复对照观看发现之前怎么都无感的贝叶斯&#xff0c;这次居然通透了&#xff01;视频链接我将放到最下方。 正文 第一…

Session与Cookie的区别(四)

咖啡寄杯的烦恼 虽然店里生意还可以&#xff0c;但小明无时无刻不想着怎么样发大财赚大钱&#xff0c;让店里的生意变得更好。 他观察到最近好多便利商店开始卖起了咖啡&#xff0c;而且时不时就买一送一或是第二件半价&#xff0c;并且贴心地提供了寄杯的服务。 寄杯就是指说你…

【Linux:线程池】

文章目录 1 线程池概念2 第一个版本的线程池3 第二个版本的线程池4 第三个版本的线程池5 STL中的容器以及智能指针的线程安全问题6 其他常见的各种锁7 读者写者问题(了解) 1 线程池概念 一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而…

【探索Linux】—— 步步学习强大的命令行工具 P.1(Linux简介)

目录 前言 一、Linux简介 二、linux的不同发行版本 三、Linux的开源性质 四、Linux的特点 五、Linux代码演示&#xff08;仅供参考&#xff09; 总结 前言 前面我们讲了C语言的基础知识&#xff0c;也了解了一些数据结构&#xff0c;并且讲了有关C的一些知识&#xff…

Vivado使用入门之一:Schematic图

目录 一、前言 二、Schematic类型 2.1 Schematic分类 2.2 RTL ANALYSIS 2.3 SYSTHESIS 2.4 IMPLEMENTATION 三、Schematic功能 3.1 界面工具栏 3.2 右键功能项对比 3.3 右键功能项说明 3.4 逻辑图界面 一、前言 在一个设计中&#xff0c;有时因定位或其他原因需要去查…

并查集练习 —岛屿数量(解法一)

题目&#xff1a; 给定一个二维数组matrix&#xff08;char[][]&#xff09;&#xff0c;里面的值不是1就是0&#xff0c;上、下、左、右相邻的1认为是一片岛。返回matrix中岛的数量。 本题共有2种解法&#xff0c;本篇先介绍最快的一种解法—递归。 分析&#xff1a; 递归的方…

第三章 关系数据库标准语言SQL

结构化查询语言&#xff08;Structed Query Language,SQL&#xff09;是关系数据库的标准语言&#xff0c;也是一个通用的&#xff0c;功能极强的关系数据库语言。 其功能不仅是查询&#xff0c;而且包括数据库模式创建&#xff0c;数据库数据的插入和修改&#xff0c;数据库安…