首页 > 编程笔记 > JavaScript笔记
Vue计算属性的使用(非常详细)
在 Vue 中,可以很方便地将数据使用插值表达式的方式渲染到页面元素中,但是插值表达式的设计初衷是用于简化运算,不应该对插值进行过多的操作。当需要进一步对插值进行处理时,可以使用 Vue 中的计算属性来完成这一操作。
通常用户会在模板中定义表达式,非常便利,Vue 的设计初衷也是用于简单运算的。但是在模板中放入太多逻辑会让模板变得臃肿且难以维护。例如:
计算属性比较适合对多个变量或者对象进行处理后返回一个结果值,也就是说多个变量中的某一个值发生了变化,则绑定的计算属性也会发生变化。
下面是完整的字符串反转的示例,定义了一个 reversedMessage 计算属性,在 input 输入框中输入字符串时,绑定的 message 属性值发生变化,触发 reversedMessage 计算属性,执行对应的函数,最终使字符串反转。
示例1:使用计算属性。
图1:字符串翻转效果
上面的示例中,当 message 属性的值改变时,reversedMessage 的值也会自动更新,并且会自动同步更新 DOM 部分。
在浏览器的控制台中修改 message 的值,按回车键执行代码,可以发现 reversedMessage 的值也发生了改变,如图2所示。
图2:修改 message 的值
默认情况下只有 getter 方法,这种情况下可以简写,例如:
示例2:getter 和 setter 方法。
图3:运行效果
在浏览器的控制台中设置计算属性 namePrice 的值为“空调5900元”,按回车键,可以发现计算属性的内容变成了“空调5900元”,效果如图4所示。
图4:修改后的效果
计算属性的写法和方法很相似,完全可以在 methods 中定义一个方法来实现相同的功能。
其实,计算属性的本质就是一个方法,只不过在使用计算属性的时候,把计算属性的名称直接作为属性来使用,并不会把计算属性作为一个方法来调用。
为什么还要使用计算属性而不是定义一个方法呢?
计算属性是基于它的依赖进行缓存的,即只有在相关依赖发生改变时,才会重新求值。例如,在示例1中,只要 message 没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
反之,如果使用方法的形式实现,当使用到 reversedMessage 方法时,无论 message 属性是否发生改变,该方法都会重新执行一次,这无形中增加了系统的开销。
在某些情况下,计算属性和方法可以实现相同的功能,但有一个重要的不同点:在调用 methods 中的一个方法时,所有方法都会被调用。
例如下面的示例定义了两个方法 add1 和 add2,分别打印 number+a、number+b,当调用其中的 add1 时,add2 也将被调用。
示例3:方法调用方式。
图5:方法的调用效果
使用计算属性则不同,计算属性相当于优化了的方法,使用时只会使用对应的计算属性。例如修改上面的示例,把 methods 换成 computed,并把 HTML 中的调用 add1 和 add2 方法的括号去掉。
注意:计算属性的调用不能使用括号,例如 add1、add2。而调用方法需要加上括号,例如 add1()、add2()。
示例4:计算属性调用方式。
图6:计算属性的调用效果
计算属性相较于方法更加优化,但并不是什么情况下都可以使用计算属性,在触发事件时还是使用对应的方法。计算属性一般在数据量比较大、比较耗时的情况下使用(例如搜索),只有虚拟 DOM 与真实 DOM 不同的情况下才会执行 computed。如果你的业务实现不需要有缓存,计算属性可以使用方法来代替。
Vue 计算属性的使用
计算属性在 Vue 的 computed 选项中定义,它可以在模板上进行双向数据绑定以展示出结果或者用作其他处理。通常用户会在模板中定义表达式,非常便利,Vue 的设计初衷也是用于简单运算的。但是在模板中放入太多逻辑会让模板变得臃肿且难以维护。例如:
<div id="app"> {{message.split('').reverse().join('')}} </div>上面的插值表达式调用了3个方法来实现字符串的反转,逻辑过于复杂,如果在模板中还要多次使用此处的表达式,就更加难以维护了,此时应该使用计算属性。
计算属性比较适合对多个变量或者对象进行处理后返回一个结果值,也就是说多个变量中的某一个值发生了变化,则绑定的计算属性也会发生变化。
下面是完整的字符串反转的示例,定义了一个 reversedMessage 计算属性,在 input 输入框中输入字符串时,绑定的 message 属性值发生变化,触发 reversedMessage 计算属性,执行对应的函数,最终使字符串反转。
示例1:使用计算属性。
<div id="app"> 原始字符串:<input type="text" v-model="message"><br/> 反转后的字符串:{{reversedMessage}} </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ message: '小庭幽圃绝清佳 ' } }, computed: { //计算属性的getter reversedMessage(){ return this.message.split('').reverse().join(''); } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,输入框下面会显示对象的反转内容,效果如图1所示。
图1:字符串翻转效果
上面的示例中,当 message 属性的值改变时,reversedMessage 的值也会自动更新,并且会自动同步更新 DOM 部分。
在浏览器的控制台中修改 message 的值,按回车键执行代码,可以发现 reversedMessage 的值也发生了改变,如图2所示。
图2:修改 message 的值
Vue 计算属性的 getter 和 setter 方法
计算属性中的每一个属性对应的都是一个对象,对象中包括 getter 和 setter 方法,分别用来获取计算属性和设置计算属性。默认情况下只有 getter 方法,这种情况下可以简写,例如:
computed: { fullNname:function(){ // } }默认情况下是不能直接修改计算属性的,如果需要修改计算属性,就需要提供一个 set 方法。例如:
computed:{ fullNname:{ //get方法 get:function(){ // } //set方法 set:function(newValue){ // } } }提示:通常情况下,getter() 方法需要使用 return 返回内容。而 setter() 方法不需要,它用来改变计算属性的内容。
示例2:getter 和 setter 方法。
<div id="app"> <p>商品名称:{{name}}</p> <p>商品价格:{{price}}</p> <p>商品名称和价格:{{namePrice}}</p> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ name:"洗衣机", price:"6800元" } }, computed:{ namePrice:{ //getter方法,显示时调用 get:function(){ //拼接name和price return this.name+ "**"+this.price; }, //setter方法,设置namePrice时调用,其中参数用来接收新设置的值 set:function(newName){ var names=newName.split(' '); //以空格拆分字符串 this.name=names[0]; this.price=names[1]; } } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,效果如图3所示。
图3:运行效果
在浏览器的控制台中设置计算属性 namePrice 的值为“空调5900元”,按回车键,可以发现计算属性的内容变成了“空调5900元”,效果如图4所示。
图4:修改后的效果
Vue 计算属性的缓存
Vue 计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时,才会重新求值。计算属性的写法和方法很相似,完全可以在 methods 中定义一个方法来实现相同的功能。
其实,计算属性的本质就是一个方法,只不过在使用计算属性的时候,把计算属性的名称直接作为属性来使用,并不会把计算属性作为一个方法来调用。
为什么还要使用计算属性而不是定义一个方法呢?
计算属性是基于它的依赖进行缓存的,即只有在相关依赖发生改变时,才会重新求值。例如,在示例1中,只要 message 没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
反之,如果使用方法的形式实现,当使用到 reversedMessage 方法时,无论 message 属性是否发生改变,该方法都会重新执行一次,这无形中增加了系统的开销。
在某些情况下,计算属性和方法可以实现相同的功能,但有一个重要的不同点:在调用 methods 中的一个方法时,所有方法都会被调用。
例如下面的示例定义了两个方法 add1 和 add2,分别打印 number+a、number+b,当调用其中的 add1 时,add2 也将被调用。
示例3:方法调用方式。
<div id="app"> <button v-on:click="a++">a+1</button> <button v-on:click="b++">b+1</button> <p>number+a={{add1()}}</p> <p>number+b={{add2()}}</p> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ a:0, b:0, number:30 } }, methods: { add1:function(){ console.log("add1"); return this.a+this.number }, add2:function(){ console.log("add2") return this.b+this.number } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,打开控制台,单击按钮,可以发现控制台调用了 add1() 和 add2() 方法,如图5所示。
图5:方法的调用效果
使用计算属性则不同,计算属性相当于优化了的方法,使用时只会使用对应的计算属性。例如修改上面的示例,把 methods 换成 computed,并把 HTML 中的调用 add1 和 add2 方法的括号去掉。
注意:计算属性的调用不能使用括号,例如 add1、add2。而调用方法需要加上括号,例如 add1()、add2()。
示例4:计算属性调用方式。
<div id="app"> <button v-on:click="a++">a+1</button> <button v-on:click="b++">b+1</button> <p>number+a={{add1}}</p> <p>number+b={{add2}}</p> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ a:0, b:0, number:30 } }, computed: { add1:function(){ console.log("number+a"); return this.a+this.number }, add2:function(){ console.log("number+b") return this.b+this.number } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,打开控制台,在页面中单击按钮,可以发现控制台只打印了 number+a,如图6所示。
图6:计算属性的调用效果
计算属性相较于方法更加优化,但并不是什么情况下都可以使用计算属性,在触发事件时还是使用对应的方法。计算属性一般在数据量比较大、比较耗时的情况下使用(例如搜索),只有虚拟 DOM 与真实 DOM 不同的情况下才会执行 computed。如果你的业务实现不需要有缓存,计算属性可以使用方法来代替。