Vue中的计算属性与监听属性

目录
  • 一、为什么要使用计算属性
    • 什么是计算属性
  • 二、计算属性和方法的区别
    • 1、区别
    • 2、计算属性使用场景
  • 三、修改计算属性的值
    • 总结
  • 四、监听属性
    • 1、监听普通属性
    • 2、监听属性和计算属性的区别
    • 3、监听复杂对象

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

什么是计算属性

计算属性:可以理解为能够在里面写一些计算逻辑的属性。具有如下的作用:

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

在数据量比较大的时候,计算属性可以帮助我们提高性能,因为计算属性只会在数据变化的时候才会计算。

在讲解计算属性之前先来看下面的一个例子:

需求:外卖套餐A每份15元,客户点了3份,总价打八折,配送费5元,要求在界面显示总价,代码如下:

<template>
    <div>
        <div>您购买了{{info.name}}共{{info.count}}份</div>
        <h1>总价:{{info.count*info.price*info.sale+info.freight}}元</h1>
    </div>
</template>

<script>
export default {
    name:'Test',
    data(){
        return{
            info:{
                userId:1,
                price:15,
                name:'套餐A',
                count:3,
                sale:0.8,
                freight:5
            }
        }
    }
}
</script>

界面运行效果:

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

<h1>总价:{{info.count*info.price*info.sale+info.freight}}元</h1>

在这段代码中,模板不在是简单的声明式逻辑,而是复杂的逻辑计算,如果想要在多处引用总价的时候,就会难以维护。所以,对于任何复杂的逻辑,都应当使用计算属性。

看下面使用计算属性的例子:

<template>
    <div>
        <h1>计算属性</h1>
        <div>您购买了{{info.name}}共{{info.count}}份</div>
        <!--使用计算属性:和绑定普通属性一样-->
        <h1>总价:{{totalPrice}}元</h1>
    </div>
</template>

<script>
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
        }
    }
}
</script>

界面显示效果:

注意:计算属性是一个属性,不是方法,不能写在methods中,放在computed属性里面。

上面计算属性的写法也可以使用ES6的写法:

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

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

1、区别

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

<template>
    <div>
        <h1>计算属性</h1>
        <div>您购买了{{info.name}}共{{info.count}}份</div>
        <!--使用计算属性:和绑定普通属性一样-->
        <h1>使用计算属性获取总价:{{totalPrice}}元</h1>
        <h1>使用方法获取总价:{{getTotalPrice()}}元</h1>
    </div>
</template>

<script>
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;
        }
    }
}
</script>

界面显示效果:

通过上面的例子可以看出:计算属性和方法实现的最终效果是相同的。那么计算属性和方法有什么区别呢?计算属性是基于它们的响应式依赖进行缓存的,只有在响应式依赖发生改变时才会重新求值。这就意味着只要响应式依赖没有发生改变,多次访问计算属性会立即返回之前的计算结果,而不必再次执行计算。相比之下,调用方法总会再次执行函数。总价计算属性和方法的区别如下:

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

看下面的例子:

<template>
    <div>
        <h1>计算属性</h1>
        <!-- <div>您购买了{{info.name}}共{{info.count}}份</div> -->
        <!-- 使用计算属性:和绑定普通属性一样 -->
        您购买了<input type="text" v-model="info.name" />
        数量<input type="text" v-model="info.count" />

        <h1>使用计算属性获取总价:{{totalPrice}}元</h1>
        <button @click="getTotalPrice">计算属性</button>
        <h1>使用方法获取总价:{{data}}元</h1>
    </div>
</template>

<script>
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;
        }
    }
}
</script>

当依赖发生改变时会多次打印“计算属性”,而方法需要在点击按钮的时候才会发生改变。依赖不发生改变时点击按钮,也会打印“方法”。如下图所示:

2、计算属性使用场景

假如我们有一个性能开销比较大的计算属性A,它需要遍历一个巨大的数组并做大量的计算,然后我们可能有其他的计算属性依赖于计算属性A。如果不使用计算属性,那么将不可避免的多次进行计算,会消耗很大的性能,这种情况下就需要使用计算属性。

三、修改计算属性的值

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

<template>
    <div>
        <h1>修改计算属性</h1>
        <h2>num:{{num}}</h2>
        <h2>计算属性num2:{{num2}}</h2>
        <button @click="change">改变计算属性的值</button>
    </div>
</template>

<script>
export default {
    name:'ComputedDemo2',
    data(){
        return{
            num:100
        }
    },
    computed:{
         num2(){
             return this.num-10;
         }
    },
    methods:{
        change(){
            this.num2=60;
        }
    }
}
</script>

效果:

这时会发现直接修改计算属性的值报错了,因为不能直接修改计算属性的值,如果要修改计算属性的值,需要修改其依赖项的值,看下面的代码:

<template>
    <div>
        <h1>修改计算属性</h1>
        <h2>num:{{num}}</h2>
        <h2>计算属性num2:{{num2}}</h2>
        <button @click="change">改变计算属性的值</button>
    </div>
</template>

<script>
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;
        }
    }
}
</script>

修改前的效果:

修改后的效果:

总结

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

四、监听属性

监听属性(watch)是用来监听data中的数据是否发生变化,一般是监听data中的某个属性。

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

1、监听普通属性

看下面的代码:

<template>
    <div>
        <h1>监听属性</h1>
        姓名:<input type="text" v-model="userName"/>
        <h1>{{userName}}</h1>
        年龄:<input type="text" v-model="age"/>
        <h1>{{age}}</h1>
    </div>
</template>

<script>
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);
        }
    }
}
</script>

界面效果:

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

监听属性和计算属性的区别主要有下面几点:

计算属性性能更优。一个监听属性只能监听一个属性的变化,如果要同时监听多个,就要写多个监听属性,而计算属性可以同时监听多个数据的变化。监听属性可以获取改变之前的属性值。计算属性能做的,watch都能做,反之则不行。能用计算属性尽量用计算属性。

需求:userName或age改变的时候打印出当前的userName和age值。

用监听属性实现:

<template>
    <div>
        <h1>监听属性</h1>
        姓名:<input type="text" v-model="userName"/>
        <h1>{{userName}}</h1>
        年龄:<input type="text" v-model="age"/>
        <h1>{{age}}</h1>
        <!--打印userName和age的值-->
        <h1>{{info}}</h1>
    </div>
</template>

<script>
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;
        }
    }
}
</script>

如果要实现上述的需求,则需要对userName和age都进行监听,监听属性里面的代码都是重复的,如果有多个,那么就要写多个监听属性。在看计算属性:

<template>
    <div>
        <h1>监听属性</h1>
        姓名:<input type="text" v-model="userName"/>
        <h1>{{userName}}</h1>
        年龄:<input type="text" v-model="age"/>
        <h1>{{age}}</h1>
        <!--打印userName和age的值-->
        <!-- <h1>{{info}}</h1> -->
        <!--使用计算属性-->
        <h1>{{getUserInfo}}</h1>
    </div>
</template>

<script>
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;
        }
    }
}
</script>

如果使用计算属性则只需要写一次就可以实现上面的需求了。

3、监听复杂对象

上面的例子中是监听的普通属性,那么如何监听对象里面的属性呢?看下面的代码:

<template>
    <div>
        <h1>监听属性</h1>
        姓名:<input type="text" v-model="userName"/>
        <h1>{{userName}}</h1>
        年龄:<input type="text" v-model="age"/>
        <h1>{{age}}</h1>
        <!--打印userName和age的值-->
        <!-- <h1>{{info}}</h1> -->
        <!--使用计算属性-->
        <h1>{{getUserInfo}}</h1>
        <!--监听对象属性-->
        <h1>监听对象属性</h1>
        姓名:<input type="text" v-model="obj.name"/>
        <h1>{{obj.name}}</h1>
    </div>
</template>

<script>
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;
        }
    }
}
</script>

效果:

能不能执行监听对象呢?答案是可以的,看下面代码:

<template>
    <div>
        <h1>监听属性</h1>
        姓名:<input type="text" v-model="userName"/>
        <h1>{{userName}}</h1>
        年龄:<input type="text" v-model="age"/>
        <h1>{{age}}</h1>
        <!--打印userName和age的值-->
        <!-- <h1>{{info}}</h1> -->
        <!--使用计算属性-->
        <h1>{{getUserInfo}}</h1>
        <!--监听对象属性-->
        <h1>监听对象属性</h1>
        姓名:<input type="text" v-model="obj.name"/>
        <h1>{{obj.name}}</h1>
        <!--监听对象-->
        <h1>监听对象</h1>
        姓名:<input type="text" v-model="obj.name"/>
        <h1>{{obj.name}}</h1>
    </div>
</template>

<script>
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;
        }
    }
}
</script>

效果:

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Vue监听属性和计算属性

    目录 一.watch监听属性 1.购物车 2.全选与取消全选 二.计算属性 1.computed 2.methods 3.setter 一.watch监听属性 这个属性用来监视某个数据的变化,并触发相应的回调函数执行. 基本用法添加watch属性,值为一个对象.对象的属性名就是要监视的数据,属性值为回调函数,每当这个属性名对应的值发生变化,就会触发该回调函数执行. 回调函数有2个参数: newVal,数据发生改变后的值. oldVal,数据发生改变前的值. 计数器: <!DOCTYPE html

  • vue计算属性和监听器实例解析

    基本实例 <div id="example"> <p>Original message: "{{ message }}"</p> <p>Computed reversed message: "{{ reversedMessage }}"</p> </div> var vm = new Vue({ el: '#example', data: { message: 'Hello'

  • vue计算属性无法监听到数组内部变化的解决方案

    vue的计算属性 计算属性可以帮助我们简化代码,做到实时更新,不用再自己添加function去修改data. 首先看一下计算属性的基本写法(摘自官网) var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar' }, computed: { fullName: function () { return this.firstName + ' ' + this.lastName } } }) 这样我们在模版里这样

  • 详解vue2.0监听属性的使用心得及搭配计算属性的使用

    我们在工作中常常需要监听某一个属性值的变化,这个时候我们就需要用到了监听属性watch,在这里我总结watch属性的三种场景使用希望对你有所帮助: 1.基础版监听: 场景如下:输入框输入你的年龄,如果年龄在0-15岁提示信息:你还是个小孩,如果年龄在 15-25岁,提示信息:你已经是个少年,如果年龄在25岁以上,提示信息:你已经长大了.根据需求配合监听属性我们得到下面的代码: <template> <div id="app"> 年齡:<input type

  • vue计算属性computed、事件、监听器watch的使用讲解

    一.计算属性(computed) <template> <div class="box"> <h1>计算属性</h1> <hr> <!-- 直接渲染得到数据 --> <p><input type="text" v-model="message"></p> <!-- 对data的数据进行简单的操作 这样有一个不好的地方就是后期对页面数据

  • 简单聊一聊vue中data的代理和监听

    目录 假设现在有一个data 需求一: 用 Object.defineProperty 定义 n 需求二:n不能小于0 所以就有了需求三:不暴露data中可以设置的属性,而是使用一个代理 因此引出了需求四:就算用户擅自修改myData,也要进行拦截 总结 接下来通过几个需求的完成来一步步看看data中的代理和监听是怎么样的 假设现在有一个data let data0 = { n:0 } 需求一: 用 Object.defineProperty 定义 n let data1 = {} Object

  • Vue中的计算属性与监听属性

    目录 一.为什么要使用计算属性 什么是计算属性 二.计算属性和方法的区别 1.区别 2.计算属性使用场景 三.修改计算属性的值 总结 四.监听属性 1.监听普通属性 2.监听属性和计算属性的区别 3.监听复杂对象 一.为什么要使用计算属性 什么是计算属性 计算属性:可以理解为能够在里面写一些计算逻辑的属性.具有如下的作用: 减少模板中的计算逻辑. 数据缓存.当我们的数据没有变化的时候,不会再次执行计算的过程. 依赖固定的数据类型(响应式数据),不能是普通的传入的一个全局数据. 在数据量比较大的时

  • 详解Vue的监听属性

    目录 Vue监听属性 什么是监听属性? 监听属性和计算属性的区别? 监听属性的使用 深度监听 立即调用 总结 Vue监听属性 什么是监听属性? 所谓监听就是对内置对象的状态或者属性变化进行监听并且做出反应的响应,监听属性,意思就是可以监视其他数据的变化. 监听属性和计算属性的区别? 计算属性是依赖的值改变后重新计算结果更新DOM,会进行缓存. 属性监听的是属性值,当定义的值发生变化时,执行相对应的函数. 最主要的用途区别: 计算属性不能执行异步任务.计算属性一般不会用来向服务器请求或者执行异步任

  • Vue监听属性图文实例详解

    目录  什么是监听属性? 监听属性和计算属性的区别? 监听属性的使用 深度监听 立即调用 写在最后  什么是监听属性?

  • Vue中computed(计算属性)和watch(监听属性)的用法及区别说明

    目录 计算属性computed 侦听属性watch 计算属性computed 支持缓存,只有依赖数据发生改变,才会重新进行计算 不支持异步,当computed内有异步操作时无效,无法监听数据的变化 computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed 如果computed属性属性值是函数,

  • Vue项目中数据的深度监听或对象属性的监听实例

    众所周知,vue项目中对数据的监听,提供了一个很好的钩子watch,watch可以极其方便的监听我们常用数据类型值的变化,但通常当我们想监听一个对象中,某个属性值的变化时,很难达到我们预期的效果.根据vue的文档,不难发现,使用数据的深度监听来达到这一效果.具体实现如下: watch: { evlist: { handler(val, oldVal) { this.isTeam = val.projectParty; this.pjtid = val.pjtid; this.isFinish =

  • vue中的计算属性和侦听属性

    计算属性 计算属性用于处理复杂的业务逻辑 计算属性具有依赖性,计算属性依赖 data中的初始值,只有当初始值改变的时候,计算属性才会再次计算 计算属性一般书写为一个函数,返回了一个值,这个值具有依赖性,只有依赖的那个值发生改变,他才会重新计算 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewpo

  • Vue中的 watch监听属性详情

    目录 一.watch监听一般数据的变化(数值,字符串,布尔值) 1.数值 2.字符串 3.布尔值 二.watch 监听 复杂类型数据的变化 1.对象 2.数组 3.对象数组 4.对象数组的属性 首先要确认 watch是一个对象,要当成对象来使用. 键:就是那个,你要监听的那个家伙: 值:可以是函数,当你监控的家伙发生变化时,需要执行的函数,这个函数有两个形参 第一个是当前值(新的值),第二个是更新前的值(旧值) 值也可以是函数名:不过这个函数名要用单引号来包裹. 值是包括选项的对象:选项包括有三

随机推荐