在模板中可以直接通过插值语法显示一些 data 中的数据
但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示
- 比如我们需要对多个 data 数据进行运算、三元运算符来决定结果、数据进行某种转化后显示
- 在模板中使用表达式,可以非常方便的实现,但是设计它们的初衷是用于简单的运算
- 在模板中放入太多的逻辑会让模板过重和难以维护
- 并且如果多个地方都使用到,那么会有大量重复的代码
演示代码:
<body>
<div id="app"> <h2>{{ firstName + " " + lastName }}</h2> <h2>{{ firstName + " " + lastName }}</h2> <h2>{{ firstName + " " + lastName }}</h2>
<h2>{{ score >= 60 ? '及格': '不及格' }}</h2>
<h2>{{ message.split(" ").reverse().join(" ") }}</h2> </div> <script src="../lib/vue.js"></script> <script> const app = Vue.createApp({ data() { return { firstName: "kobe", lastName: "bryant",
score: 80,
message: "my name is fredo" } }, })
app.mount("#app") </script> </body>
|
我们有没有什么方法可以将逻辑抽离出去呢?
- 可以,其中一种方式就是将逻辑抽取到一个 methods 中,放到 methods 的 options 中
- 但是,这种做法有一个直观的弊端,就是所有的 data 使用过程都会变成了一个方法的调用
- 另外一种方式就是使用计算属性 computed
computed 和 methods 区别
对于 computed 官方并没有给出直接的概念解释,
而是说, 对于任何包含响应式数据的复杂逻辑,都应该使用计算属性
而计算属性 computed 和 methods 看起来是一样的, 其实不然
演示代码:
<body>
<div id="app"> <h2>{{ getFullname() }}</h2> <h2>{{ getFullname() }}</h2> <h2>{{ getFullname() }}</h2>
<h2>{{ fullname }}</h2> <h2>{{ fullname }}</h2> <h2>{{ fullname }}</h2>
<button @click="changeLastname">修改lastname</button> </div> <script src="../lib/vue.js"></script> <script> const app = Vue.createApp({ data() { return { firstName: "kobe", lastName: "bryant" } }, methods: { getFullname() { console.log("getFullname-----") return this.firstName + " " + this.lastName }, changeLastname() { this.lastName = "fredo" } }, computed: { fullname() { console.log("computed fullname-----") return this.firstName + " " + this.lastName } } })
app.mount("#app") </script> </body>
|
可以发现:
methods 的函数, 每使用一次就调用一次, 而 computed 则只会调用一次
- 这是因为计算属性会基于它们的依赖关系进行缓存
- 在数据不发生变化时,计算属性是不需要重新计算的
- 但是如果依赖的数据发生变化,在使用时,计算属性依然会重新进行计算
计算属性在大多数情况下,只需要一个 getter 方法即可,所以我们会将计算属性直接写成一个函数, 其实在 computed 中是对象, 仅仅是 Vue 的语法糖写法, 简写成函数的样式
- 对象就会有 get 和 set 方法
- 只有 get 方法时, 可以简写
<body>
<div id="app"> <h2>{{ fullname }}</h2>
<button @click="setFullname">设置fullname</button> </div> <script src="../lib/vue.js"></script> <script> const app = Vue.createApp({ data() { return { firstname: "coder", lastname: "fredo" } }, computed: { fullname: { get: function() { return this.firstname + " " + this.lastname }, set: function(value) { const names = value.split(" ") this.firstname = names[0] this.lastname = names[1] } } }, methods: { setFullname() { this.fullname = "kobe bryant" } } })
app.mount("#app") </script> </body>
|