Vue3 计算属性

计算属性的关键词为 computed,当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值,计算属性在处理一些复杂逻辑时是很有用的。

为什么要使用 computed 呢?我们知道,在模板内使用表达式非常普遍的,但是,在模板内的放入太多逻辑的表达式,会使得模板变得很重,难于维护。

以下是反转字符串的例子:

<div id="app">
  {{ message.split('').reverse().join('') }}
</div>

我要试一试

在上面的实例中,模板里的表达式变得很复杂,我们需要花费上一小段时间去理解,这块内容到底渲染的是什么?其实是将 message 进行字符串翻转。

然而,当初模板中使用表达式的初衷时为了简单运算的。所以,从这点出发,我们是不是就不建议在模板中使用过于复杂的表达式了。此时,计算属性就横空出世了。计算属性就是当依赖的属性的值发生变化的时候,才会触发他的更改,如果依赖的值,不发生变化的时候,使用的是缓存中的属性值。

接下来我们看看使用了计算属性的实例:

<div>菜鸟教程'
      }
    },
    computed: {
      // 计算属性的 getter
      reversedMessage: function () {
        // `this` 指向 vm 实例
        return this.message.split('').reverse().join('')
      }
    }
}
   
Vue.createApp(app).mount('#app')
</script>

我要试一试

在上面的实例中,我们声明了一个计算属性 reversedMessage,提供的函数将用作属性 vm.reversedMessage 的 getter。

vm.reversedMessage 依赖于 vm.message,在 vm.message 发生改变时,vm.reversedMessage 也会更新。

 

1. computed 与 methods 的差别

我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。

通常情况下,我们是通过视觉效果无法看出两者的差别的。但是使用 computed 性能会更好。如果你不希望缓存,你可以使用 methods 属性。

 

2. computed 的 getter 函数

在 vue 中,computed 的属性可以被视为是 data 一样,可以读取和设置它的值。因此,在 computed 中可以分为 getter(读取) 和 setter (设值),一般情况下,是没有 setter 的,computed 只是预设了 getter,也就是只能读取,不可以改变设值。所以,computed 默认格式如下:

其中 html 代码如下:

<div>
    message: {{message}}
</div>

<!-- 计算属性 -->
<div>
    计算属性: {{updateMessage}}
</div>
</pre>  

其中 js 代码如下:

computed: {
    updateMessage(): {
            console.log('计算属性', this.message)
            return this.message
    }
}

js 代码等同于:

computed: {
    updateMessage: {
        get: function() {
            console.log('计算属性', this.message)
            return this.message
        }
    }
}

 

3. computed 的 setter 函数

computed 属性默认只有 getter,不过在需要时也可以提供一个 setter:

var app = {
    data() {
        return {
        name: 'Google',
        url: 'http://www.google.com'
        }
    },
    computed: {
        site: {
        // getter
        get: function () {
            return this.name + ' ' + this.url
        },
        // setter
        set: function (newValue) {
            var names = newValue.split(' ')
            this.name = names[0]
            this.url = names[names.length - 1]
        }
        }
    }
}
vm = Vue.createApp(app).mount('#app')
// 调用 setter, vm.name 和 vm.url 也会被对应更新
vm.site = '菜鸟教程 https://www.cainiaojc.com';
document.write('name: ' + vm.name);
document.write('<br>');
document.write('url: ' + vm.url);

我要试一试

运行 vm.site = '菜鸟教程 https://www.cainiaojc.com'; 时,setter 会被调用, vm.name 和 vm.url 也会被对应更新。