Vue语法--计算属性

简介: Vue语法--计算属性

一. 计算属性



1. 什么是计算属性?


通常, 我们是在模板中, 通过插值语法显示data的内容, 但有时候我们可能需要在{{}}里添加一些计算, 然后在展示出来数据. 这时我们可以使用到计算属性


先来举个例子, 比如: 一个班, 有几个学生参加期末考试, 要计算考试的平均分. 我们来看看, 通常要怎么做?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">考试成绩
    <ul>
        <li v-for="stu in students">{{stu.name}} -- {{stu.score}}</li>
    </ul>
    <p>平均分: <label>{{getAvg()}}</label></p>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            message:"班级考试平均分",
            students: [
                {name:"张三", score:90},
                {name:"lisi", score:100},
                {name:"wangwu", score:99},
                {name:"zhaoliu", score:89},
                {name:"liuqi", score:95}
            ]
        },
        methods: {
            getAvg() {
                let sum = 0;
                 for (let i = 0; i < this.students.length; i++) {
                     console.log(this.students[i].score);
                     let stu = this.students[i];
                     sum += stu.score;
                 }
                 console.log("平均分:" + sum/this.students.length);
                 return sum/this.students.length;
            }
        }
    })
</script>
</body>
</html>

我们定义了一组学生的成绩. 然后将其显示在页面上, 然后通过方法getAvg计算平均分.


1187916-20210220063957352-1765421474.png

 

这里我们在获取平均分的时候, 使用的是{{getAve()}} 其实, 平均分我们理解更像是一个属性, 而不是一个方法. 为了方便计算, vue给我们提供了一个computed属性, 专门用来做计算. computed中定义的也是方法, 这个方法的方法名通常都定义为名词. 我们来看一下使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">考试成绩
    <ul>
        <li v-for="stu in students">{{stu.name}} -- {{stu.score}}</li>
    </ul>
    <p>平均分: <label>{{avg}}</label></p>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            message:"班级考试平均分",
            students: [
                {name:"zhangsan", score:90},
                {name:"lisi", score:100},
                {name:"wangwu", score:99},
                {name:"zhaoliu", score:89},
                {name:"liuqi", score:95}
            ]
        },
        computed: {
            avg: function() {
                let sum = 0;
                for (let i = 0; i < this.students.length; i++) {
                    console.log(this.students[i].score);
                    let stu = this.students[i];
                    sum += stu.score;
                }
                console.log("平均分:" + sum/this.students.length);
                return sum/this.students.length;
            }
        },
        methods: {
        }
    })
</script>
</body>
</html>

这里,增加了一个computed属性, 里面定义了avg方法, 没错, 本质还是方法, 但命名的时候, 将其命名为名词.


眼尖的同学应该已经发现了, 这好像和methods方法一样啊, 就是换了个名字. 那computed计算属性和methods方法有什么区别呢?


2. 计算属性computed的缓存功能


我们用案例来说明他们之间的区别.


案例1. methods方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <p> Origin Message: {{message}}</p>
    <p>Mthod Message:{{getMessage()}}</p>
    <p>Mthod Grade:{{getGrade()}}</p>
    <p>Mthod Class:{{getClass()}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            message:"班级考试平均分",
            className: "1班",
            gradeName:"一年级"
        },
        methods: {
            getGrade: function(){
                console.log("调用Grade计算")
                return "方法" + this.gradeName
            },
            getClass: function(){
                console.log("调用class计算")
                return "方法" + this.className
            },
            getMessage: function(){
                console.log("调用message计算")
                return "方法" + this.message
            }
        }
    })
</script>
</body>
</html>

1187916-20210220071318140-1474777228.png

我们发现, 在修改一个属性, 其他属性都没变化的情况下, 我们发现methods里的方法都被执行了一遍


案例2. computed计算属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <p> Origin Message: {{message}}</p>
    <p>Mthod Message:{{getMessage}}</p>
    <p>Mthod Grade:{{getGrade}}</p>
    <p>Mthod Class:{{getClass}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            message:"班级考试平均分",
            className: "1班",
            gradeName:"一年级"
        },
        computed: {
            getGrade: function(){
                console.log("调用Grade计算")
                return "方法" + this.gradeName
            },
            getClass: function(){
                console.log("调用class计算")
                return "方法" + this.className
            },
            getMessage: function(){
                console.log("调用message计算")
                return "方法" + this.message
            }
        }
    })
</script>
</body>
</html>

控制台输出



我们发现, 当控制台修改其中一个属性值, 只有调用这个属性的方法会重新执行

 

案例3:  再看一个computed缓存的例子


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <p>调用方法</p>
    <p>{{getMes()}}</p>
    <p>{{getMes()}}</p>
    <p>{{getMes()}}</p>
    <p>{{getMes()}}</p>
    <p>调用计算属性</p>
    <p>{{mes}}</p>
    <p>{{mes}}</p>
    <p>{{mes}}</p>
    <p>{{mes}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            firstName: "Elon",
            lastName: "Musk"
        },
        computed: {
            mes: function(){
                console.log("调用计算属性")
                return this.firstName + " " + this.lastName
            }
        },
        methods: {
            getMes: function(){
                console.log("调用method方法")
                return  this.firstName  + " " +  this.lastName
            }
        }
    })
</script>
</body>
</html>


这是两种方式的调用, 但是结果都一样, 都是打印输出姓名, 计算属性mes调用了四次, 方法getMes()也调用了四次, 我们来看看运行结果

1187916-20210220071016457-373127418.png

两次打印的结果是一样的, 但是调用getMes()调用了4次, 而mes计算属性只计算了一次.

 

总结



  • methods方法和computed计算属性,两种方式的最终结果确实是完全相同
  • 不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值,多次访问getMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
  • methods方法,每当触发重新渲染时,调用方法将总会再次执行函数。

所以,官网说,对于任何复杂逻辑,都应当使用计算属性。


3. 计算属性的getter和setter访问器


问题: 我们发现, 在计算属性和methods方法调用的是偶还有一点不同, 那就是调用方式不同. method方调用是{{getMessage()}}, 而计算属性是{{getMessage}}, 我们上面不是说计算属性中定义的也是方法么? 为什么不需要使用()呢? 下面来研究一下

还是这个案例, 我们来看看代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">{{message}} {{avg}}</div>
<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: "计算平均分:",
            students: [
                {name:"zhangsan", score:90},
                {name:"lisi", score:100},
                {name:"wangwu", score:99},
                {name:"zhaoliu", score:89},
                {name:"liuqi", score:95}
            ]
        },
        computed: {
            avg: function() {
                let sum = 0;
                for (let i = 0; i < this.students.length; i++) {
                    console.log(this.students[i].score);
                    let stu = this.students[i];
                    sum += stu.score;
                }
                console.log("平均分:" + sum/this.students.length);
                return sum/this.students.length;
            }
        }
    });
</script>
</body>
</html>

我们在计算平均分的时候, 是把avg当做一个属性来对待的, 所以,调用的时候这么写{{avg}}, 而不是{{avg()}}. 但是我们定义的时候却是给定义成方法了, 为什么会这样呢?

下面我们来研究computed完整的写法, 研究完这个, 就知道为什么这么写了.

 

  • 其实计算属性本身是定义为了一个属性. 例如: 我们定义test, 通常我们定义属性是这么定义的


test: "这是一个属性"

  • 在计算属性里, 属性值是一个对象, 所以, 我们要这么定义
computed: {
    test: {
    }
}


  • 对象的内部有两个方法, 一个是get方法, 一个是set方法. 这时在get方法中return一个abc, 这是, 在页面显示的就应该是abc
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">{{message}} --- {{avg}} --- {{test}}</div>
<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: "计算平均分:",
            students: [
                {name:"zhangsan", score:90},
                {name:"lisi", score:100},
                {name:"wangwu", score:99},
                {name:"zhaoliu", score:89},
                {name:"liuqi", score:95}
            ]
        },
        computed: {
            avg: function() {
                let sum = 0;
                for (let i = 0; i < this.students.length; i++) {
                    console.log(this.students[i].score);
                    let stu = this.students[i];
                    sum += stu.score;
                }
                console.log("平均分:" + sum/this.students.length);
                return sum/this.students.length;
            },
            test : {
                set: function(newValue) {
                    this.message = newValue;
                    console.log("调用setter")
                },
                get: function() {
                    return "abc" 
                }
            }
        }
    });
</script>
</body>
</html>

看看效果

1187916-20210220123217831-920015448.png


确实打印输出了abc

 

 

  • 因为有get方法和set方法, 所以, 我们可以修改test的值,  如下: 修改了app.test的值, 最终改变了message的值.

 1187916-20210220124806013-1511628019.png

  • 然而, 计算属性通常只实现get方法, 而不实现set方法. 我们是计算后输出, 而不允许北外不修改,  这时计算属性就只剩下一个get方法, 最后我们将其简写, 去掉get, 就是我们通常看到的写法
computed: {
    avg: function() {
        let sum = 0;
        for (let i = 0; i < this.students.length; i++) {
            console.log(this.students[i].score);
            let stu = this.students[i];
            sum += stu.score;
        }
        console.log("平均分:" + sum/this.students.length);
        return sum/this.students.length;
    },
    avg1 : function() {
            return "abc" 
    }
}


虽然写法和method差不多. 但本质上, 计算属性还是属性, 所以, 和属性的写法是一样的.

相关文章
|
8天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
7天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉
|
7天前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。自学前端2年半,熟悉JavaScript与Vue,正向全栈方向发展。博客内容涵盖Vue基础、列表展示及计数器案例等,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
|
22天前
|
数据采集 监控 JavaScript
在 Vue 项目中使用预渲染技术
【10月更文挑战第23天】在 Vue 项目中使用预渲染技术是提升 SEO 效果的有效途径之一。通过选择合适的预渲染工具,正确配置和运行预渲染操作,结合其他 SEO 策略,可以实现更好的搜索引擎优化效果。同时,需要不断地监控和优化预渲染效果,以适应不断变化的搜索引擎环境和用户需求。
|
8天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
8天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
8天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
9天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
9天前
|
存储 JavaScript
Vue 组件间如何通信
Vue组件间通信是指在Vue应用中,不同组件之间传递数据和事件的方法。常用的方式有:props、自定义事件、$emit、$attrs、$refs、provide/inject、Vuex等。掌握这些方法可以实现父子组件、兄弟组件及跨级组件间的高效通信。
|
14天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发