运维开发网

一键复制 Vue中的计算属性和监控属性

运维开发网 https://www.qedev.com 2022-10-06 14:58 出处:网络
这篇文章介绍了Vue中的计算属性与监听属性,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

这篇文章介绍了Vue中的计算属性与监听属性,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下


一、为什么要使用计算属性


什么是计算属性

计算属性:可以理解为一种属性,在其中可以编写一些计算逻辑。具有以下功能:

减少模板中的计算逻辑。数据缓存。当我们的数据没有变化的时候,不会再次执行计算的过程。依赖固定的数据类型(响应式数据),不能是普通的传入的一个全局数据。

当数据量较大时,计算属性可以帮助我们提高性能,因为计算属性只有在数据发生变化时才会被计算。

在解释计算属性之前,让我们看一下下面的示例:

需求:外卖套餐A在15元,顾客订了3份,总价打八折。送货费是5元。界面上需要显示总价,代码如下:

lt;templategt; lt;divgt; lt;divgt;您购买了{{info.name}}共{{info.count}}份lt;/divgt; lt;h1gt;总价:{{info.count*info.price*info.sale+info.freight}}元lt;/h1gt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'Test', data(){ return{ info:{ userId:1, price:15, name:'套餐A', count:3, sale:0.8, freight:5 } } }}lt;/scriptgt;

界面操作效果:


看了上面的例子,可能有人会问:如果已经用这种方法实现了需求,为什么还需要使用计算属性呢?我们知道,vue中模板中的表达式是非常方便的,最初是为了简单操作而设计的。如果在模板中放入过多的逻辑会使模板过于沉重,难以维护,那么看看上面的代码:

lt;h1gt;总价:{{info.count*info.price*info.sale+info.freight}}元lt;/h1gt;

在这段代码中,模板不再是简单的声明性逻辑,而是复杂的逻辑计算。如果要参考多个地方的总价,就很难维持了。因此,对于任何复杂的逻辑,都应该使用计算属性。

请看以下使用计算属性的示例:

lt;templategt; lt;divgt; lt;h1gt;计算属性lt;/h1gt; lt;divgt;您购买了{{info.name}}共{{info.count}}份lt;/divgt; lt;!--使用计算属性:和绑定普通属性一样--gt; lt;h1gt;总价:{{totalPrice}}元lt;/h1gt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'ComputedDemo', data(){ return{ info:{ userId:1, price:15, name:'套餐A', count:3, sale:0.8, freight:5 } } }, computed:{ // 定义计算属性totalPrice totalPrice:function(){ return this.info.count*this.info.price*this.info.sale+this.info.freight } }}lt;/scriptgt;

界面显示效果:


注意:计算属性是一个属性,而不是一个方法。它不能写在方法中,而是放在计算属性中。

上述计算属性也可以写成ES6:

// 使用ES6写法totalPrice(){ return this.info.count*this.info.price*this.info.sale+this.info.freight}


二、计算属性和方法的区别


1、区别

除了计算属性之外,还可以使用方法来实现上面的示例:

lt;templategt; lt;divgt; lt;h1gt;计算属性lt;/h1gt; lt;divgt;您购买了{{info.name}}共{{info.count}}份lt;/divgt; lt;!--使用计算属性:和绑定普通属性一样--gt; lt;h1gt;使用计算属性获取总价:{{totalPrice}}元lt;/h1gt; lt;h1gt;使用方法获取总价:{{getTotalPrice()}}元lt;/h1gt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'ComputedDemo', data(){ return{ info:{ userId:1, price:15, name:'套餐A', count:3, sale:0.8, freight:5 } } }, computed:{ // 定义计算属性totalPrice // totalPrice:function(){ // return this.info.count*this.info.price*this.info.sale+this.info.freight; // } // 使用ES6写法 totalPrice(){ return this.info.count*this.info.price*this.info.sale+this.info.freight; } }, methods:{ getTotalPrice(){ return this.info.count*this.info.price*this.info.sale+this.info.freight; } }}lt;/scriptgt;

界面显示效果:


从上面的例子可以看出,计算属性和方法的最终效果是一样的。那么计算属性和方法有什么区别呢?属性基于它们的响应依赖关系被缓存,并且仅当响应依赖关系改变时才被重新评估。这意味着,只要响应依赖关系没有改变,对计算属性的多次访问将立即返回先前的计算结果,而不必再次执行计算。相反,调用方法总是会再次执行函数。总价属性和方法的区别如下:

计算属性在依赖发生改变时会自动改变,而方法在依赖发生改变时需要触发才会改变。计算属性在依赖发生改变时才会重新计算,而方法在每次调用时都会执行。

请看下面的例子:

lt;templategt; lt;divgt; lt;h1gt;计算属性lt;/h1gt; lt;!-- lt;divgt;您购买了{{info.name}}共{{info.count}}份lt;/divgt; --gt; lt;!-- 使用计算属性:和绑定普通属性一样 --gt; 您购买了lt;input type="text" v-model="info.name" /gt; 数量lt;input type="text" v-model="info.count" /gt; lt;h1gt;使用计算属性获取总价:{{totalPrice}}元lt;/h1gt; lt;button @click="getTotalPrice"gt;计算属性lt;/buttongt; lt;h1gt;使用方法获取总价:{{data}}元lt;/h1gt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'ComputedDemo', data(){ return{ info:{ userId:1, price:15, name:'套餐A', count:3, sale:0.8, freight:5 }, data:0 } }, computed:{ // 定义计算属性totalPrice // totalPrice:function(){ // return this.info.count*this.info.price*this.info.sale+this.info.freight; // } // 使用ES6写法 totalPrice(){ console.log('计算属性'); return this.info.count*this.info.price*this.info.sale+this.info.freight; } }, methods:{ getTotalPrice(){ console.log('方法'); this.data= this.info.count*this.info.price*this.info.sale+this.info.freight; } }}lt;/scriptgt;

当依赖关系改变时,ldquo会被多次打印;评估属性rdquo并且当点击按钮时需要改变方法。当依赖关系不变时点击按钮,ldquo也会被打印出来;方法rdquo。如下图所示:



2、计算属性使用场景

如果我们有一个高性能代价的计算属性A,它需要遍历一个巨大的数组,做大量的计算,然后我们可能会有其他依赖于计算属性A的计算属性,如果你不使用计算属性,它必然会被计算很多次,会消耗很多性能。在这种情况下,您需要使用计算属性。


三、修改计算属性的值

在上面的例子中,计算属性的值是通过使用获得的,那么如何修改计算属性的值呢?请看下面的例子:

lt;templategt; lt;divgt; lt;h1gt;修改计算属性lt;/h1gt; lt;h2gt;num:{{num}}lt;/h2gt; lt;h2gt;计算属性num2:{{num2}}lt;/h2gt; lt;button @click="change"gt;改变计算属性的值lt;/buttongt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'ComputedDemo2', data(){ return{ num:100 } }, computed:{ num2(){ return this.num-10; } }, methods:{ change(){ this.num2=60; } }}lt;/scriptgt;

效果:


这时你会发现,直接修改计算属性的值会给出一个错误,因为你不能直接修改计算属性的值。如果要修改计算属性的值,需要修改其依赖项的值。请参见以下代码:

lt;templategt; lt;divgt; lt;h1gt;修改计算属性lt;/h1gt; lt;h2gt;num:{{num}}lt;/h2gt; lt;h2gt;计算属性num2:{{num2}}lt;/h2gt; lt;button @click="change"gt;改变计算属性的值lt;/buttongt; lt;/divgt;lt;/templategt;lt;scriptgt;import { get } from 'http';export default { name:'ComputedDemo2', data(){ return{ num:100 } }, computed:{ num2:{ // 当计算属性要修改时先触发set方法 // 读取当前计算属性中的值,get方法可以隐藏,默认进入的是get方法 get:function(){ return this.num-10; }, set:function(val){ this.num=val; } } }, methods:{ change(){ // 计算属性不能直接修改 this.num2=60; } }}lt;/scriptgt;

修改前的效果:


修改后的效果:



总结

不能修改计算属性的值。如果要修改计算属性的值,必须通过计算属性中的set方法修改其依赖项的值。


四、监听属性

监控属性(watch)用于监控数据中的数据是否发生变化,通常是监控数据中的某个属性。

更加灵活、通用的API。watch中可以执行任何逻辑,如函数节流,Ajax异步获取数据,甚至操作DOM。


1、监听普通属性

请看下面的代码:

lt;templategt; lt;divgt; lt;h1gt;监听属性lt;/h1gt; 姓名:lt;input type="text" v-model="userName"/gt; lt;h1gt;{{userName}}lt;/h1gt; 年龄:lt;input type="text" v-model="age"/gt; lt;h1gt;{{age}}lt;/h1gt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'watchDemo', data(){ return{ userName:"abc", age:23 } }, methods:{ change(){ } }, watch:{ // 监听userName的变化 // 有两个参数,newValue表示变化后的值,oldValue表示变化前的值 userName:function(newValue,oldValue){ console.log('修改前的值:'+oldValue); console.log('修改后的值:'+newValue); }, // 监听age的变化 age:function(newValue,oldValue){ console.log('修改前的值:'+oldValue); console.log('修改后的值:'+newValue); } }}lt;/scriptgt;

界面效果:



2、监听属性和计算属性的区别

监视属性和计算属性之间的主要区别如下:

属性表现更好。一个监控属性只能监控一个属性的变化。如果要同时监控多个属性,就要写多个监控属性,而计算属性可以同时监控多个数据的变化。侦听属性以获取更改前的属性值。属性能做什么,手表就能做什么,反之亦然。您可以使用计算属性。尽可能使用计算属性。

要求:当用户名或年龄改变时,打印出当前的用户名和年龄值。

用监听属性实现:

lt;templategt; lt;divgt; lt;h1gt;监听属性lt;/h1gt; 姓名:lt;input type="text" v-model="userName"/gt; lt;h1gt;{{userName}}lt;/h1gt; 年龄:lt;input type="text" v-model="age"/gt; lt;h1gt;{{age}}lt;/h1gt; lt;!--打印userName和age的值--gt; lt;h1gt;{{info}}lt;/h1gt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'watchDemo', data(){ return{ userName:"abc", age:23, info:'' } }, methods:{ change(){ } }, watch:{ // 监听userName的变化 // 有两个参数,newValue表示变化后的值,oldValue表示变化前的值 userName:function(newValue,oldValue){ // console.log('修改前的值:'+oldValue); // console.log('修改后的值:'+newValue); this.info= '我的姓名:'+ this.userName+',年龄:'+this.age; }, // 监听age的变化 age:function(newValue,oldValue){ // console.log('修改前的值:'+oldValue); // console.log('修改后的值:'+newValue); this.info= '我的姓名:'+ this.userName+',年龄:'+this.age; } }}lt;/scriptgt;

要实现上述需求,需要同时监控用户名和年龄,监控属性中的代码都是重复的。如果不止一个,那么就需要编写多个监控属性。查看计算属性:

lt;templategt; lt;divgt; lt;h1gt;监听属性lt;/h1gt; 姓名:lt;input type="text" v-model="userName"/gt; lt;h1gt;{{userName}}lt;/h1gt; 年龄:lt;input type="text" v-model="age"/gt; lt;h1gt;{{age}}lt;/h1gt; lt;!--打印userName和age的值--gt; lt;!-- lt;h1gt;{{info}}lt;/h1gt; --gt; lt;!--使用计算属性--gt; lt;h1gt;{{getUserInfo}}lt;/h1gt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'watchDemo', data(){ return{ userName:"abc", age:23, info:'' } }, methods:{ change(){ } }, // watch:{ // // 监听userName的变化 // // 有两个参数,newValue表示变化后的值,oldValue表示变化前的值 // userName:function(newValue,oldValue){ // // console.log('修改前的值:'+oldValue); // // console.log('修改后的值:'+newValue); // this.info= '我的姓名:'+ this.userName+',年龄:'+this.age; // }, // // 监听age的变化 // age:function(newValue,oldValue){ // // console.log('修改前的值:'+oldValue); // // console.log('修改后的值:'+newValue); // this.info= '我的姓名:'+ this.userName+',年龄:'+this.age; // } // } computed:{ getUserInfo(){ return '我的姓名:'+ this.userName+',年龄:'+this.age; } }}lt;/scriptgt;

如果使用计算属性,只需要编写一次就可以实现上述要求。


3、监听复杂对象

在上面的例子中,它是一个常见的监控属性,那么如何监控对象中的属性呢?请看下面的代码:

lt;templategt; lt;divgt; lt;h1gt;监听属性lt;/h1gt; 姓名:lt;input type="text" v-model="userName"/gt; lt;h1gt;{{userName}}lt;/h1gt; 年龄:lt;input type="text" v-model="age"/gt; lt;h1gt;{{age}}lt;/h1gt; lt;!--打印userName和age的值--gt; lt;!-- lt;h1gt;{{info}}lt;/h1gt; --gt; lt;!--使用计算属性--gt; lt;h1gt;{{getUserInfo}}lt;/h1gt; lt;!--监听对象属性--gt; lt;h1gt;监听对象属性lt;/h1gt; 姓名:lt;input type="text" v-model="obj.name"/gt; lt;h1gt;{{obj.name}}lt;/h1gt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'watchDemo', data(){ return{ userName:"abc", age:23, info:'', // 对象 obj:{ name:'123' } } }, methods:{ change(){ } }, watch:{ // 监听userName的变化 // 有两个参数,newValue表示变化后的值,oldValue表示变化前的值 userName:function(newValue,oldValue){ // console.log('修改前的值:'+oldValue); // console.log('修改后的值:'+newValue); this.info= '我的姓名:'+ this.userName+',年龄:'+this.age; }, // 监听age的变化 age:function(newValue,oldValue){ // console.log('修改前的值:'+oldValue); // console.log('修改后的值:'+newValue); this.info= '我的姓名:'+ this.userName+',年龄:'+this.age; }, // 监听对象中属性的变化 'obj.name':function(newValue,oldValue){ console.log('修改前的值:'+oldValue); console.log('修改后的值:'+newValue); } }, computed:{ getUserInfo(){ return '我的姓名:'+ this.userName+',年龄:'+this.age; } }}lt;/scriptgt;

效果:


可以执行监控对象吗?答案是肯定的,看下面这段代码:

lt;templategt; lt;divgt; lt;h1gt;监听属性lt;/h1gt; 姓名:lt;input type="text" v-model="userName"/gt; lt;h1gt;{{userName}}lt;/h1gt; 年龄:lt;input type="text" v-model="age"/gt; lt;h1gt;{{age}}lt;/h1gt; lt;!--打印userName和age的值--gt; lt;!-- lt;h1gt;{{info}}lt;/h1gt; --gt; lt;!--使用计算属性--gt; lt;h1gt;{{getUserInfo}}lt;/h1gt; lt;!--监听对象属性--gt; lt;h1gt;监听对象属性lt;/h1gt; 姓名:lt;input type="text" v-model="obj.name"/gt; lt;h1gt;{{obj.name}}lt;/h1gt; lt;!--监听对象--gt; lt;h1gt;监听对象lt;/h1gt; 姓名:lt;input type="text" v-model="obj.name"/gt; lt;h1gt;{{obj.name}}lt;/h1gt; lt;/divgt;lt;/templategt;lt;scriptgt;export default { name:'watchDemo', data(){ return{ userName:"abc", age:23, info:'', // 对象 obj:{ name:'123' } } }, methods:{ change(){ } }, watch:{ // 监听userName的变化 // 有两个参数,newValue表示变化后的值,oldValue表示变化前的值 userName:function(newValue,oldValue){ // console.log('修改前的值:'+oldValue); // console.log('修改后的值:'+newValue); this.info= '我的姓名:'+ this.userName+',年龄:'+this.age; }, // 监听age的变化 age:function(newValue,oldValue){ // console.log('修改前的值:'+oldValue); // console.log('修改后的值:'+newValue); this.info= '我的姓名:'+ this.userName+',年龄:'+this.age; }, // 监听对象中属性的变化 // 'obj.name':function(newValue,oldValue){ // console.log('修改前的值:'+oldValue); // console.log('修改后的值:'+newValue); // } // 直接监听对象 obj:{ // handler表示默认执行的函数 handler(newValue,oldValue){ console.log('修改前的值:') console.log(oldValue); console.log('修改后的值:'); console.log(newValue); }, // 表示深度监听 // true:表示handler函数会执行 // false:表示handler函数不会执行 deep:true } }, computed:{ getUserInfo(){ return '我的姓名:'+ this.userName+',年龄:'+this.age; } }}lt;/scriptgt;

效果:


GitHub代码地址:https://github.com/JiangXiaoLiang1988/computed.git

这就是本文的全部内容。希望对大家的学习有帮助

0

精彩评论

暂无评论...
验证码 换一张
取 消