Chapter 05 计算属性

news/2024/11/14 1:38:04/

欢迎大家订阅【Vue2+Vue3】入门到实践 专栏,开启你的 Vue 学习之旅!

文章目录

  • 前言
  • 一、基础语法
  • 二、计算属性vs方法
  • 三、完整写法


前言

Vue.js 提供了丰富的功能,帮助开发者高效地构建用户界面。本篇文章详细讲解了其计算属性的基本语法、应用场景以及性能差异。

一、基础语法

①定义
计算属性是基于其他数据属性的值计算而来的衍生数据。
它通过一个函数自动重新计算,能够简化模板中的逻辑,提高代码的可读性和可维护性。计算属性不仅仅是封装了一段代码,它还能根据依赖的数据变化进行反应式更新。

②默认写法

computed:{计算属性名(){一段代码逻辑(计算逻辑)return 结果}
}

① 声明在 computed 配置项中,一个计算属性对应一个函数
② 使用起来和普通属性一样使用 {{ 计算属性名 }}
计算属性 → 可以将一段 求值的代码 进行封装

【示例】

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>table {border: 1px solid #000;text-align: center;width: 240px;}th,td {border: 1px solid #000;}h3 {position: relative;}</style>
</head>
<body><div id="app"><h3>礼物清单</h3><table><tr><th>名字</th><th>数量</th></tr><tr v-for="(item, index) in list" :key="item.id"><td>{{ item.name }}</td><td>{{ item.num }}个</td></tr></table><!-- 目标:统计求和,求得礼物总数 --><p>礼物总数:{{totalCount}} 个</p></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {// 现有的数据list: [{ id: 1, name: '篮球', num: 1 },{ id: 2, name: '玩具', num: 2 },{ id: 3, name: '铅笔', num: 5 },]},computed:{totalCount(){// 基于现有的数据,编写求值逻辑// 计算属性函数内部可直接通过 this 访问到 app 实例//需求:对 this.list 数值里面的 num 进行求和→reducelet total = this.list.reduce((sum,item)=>sum+item.num,0)return total}}})</script>
</body>
</html>

运行结果:
在这里插入图片描述
【分析】

let total = this.list.reduce((sum, item) => sum + item.num, 0);

reduce() :数组的一个方法,它用于对数组中的每个元素执行一个函数,将其汇总为一个单一的结果。reduce 方法接受两个参数:

  • 参数1:一个回调函数。
  • 参数2:一个初始值,通常情况下是 0。

(sum, item) => sum + item.num:一个箭头函数,作为 reduce 的第一个参数。我们可以把该函数拆分成两个部分:

  • sum:表示累加器,它是上一次调用函数返回的值。
  • item:表示当前处理的数组元素。
  • 函数内部的逻辑 sum + item.num:将当前的累加器 sum 和当前对象的 num 属性相加,并返回这个结果。这个返回值会成为下一次调用的 sum 值。
  • 0 :表示累加的初始值是 0。第一次调用时,sum 的初始值为 0。

该代码遍历 this.list 数组中的每一个项(item),对于每一个 item,提取它的 num 值,并不断地将这些 num 值相加到 sum 中,最终,返回所有 num 值的总和并赋给 total 变量。
执行过程如下:

第一步:sum = 0, item = { id: 1, name: '篮球', num: 1 } → 0 + 1 = 1
第二步:sum = 1, item = { id: 2, name: '玩具', num: 2 } → 1 + 2 = 3
第三步:sum = 3, item = { id: 3, name: '铅笔', num: 5 } → 3 + 5 = 8

二、计算属性vs方法

特性计算属性 (computed)方法 (methods)
定义基于现有的数据,计算出新属性提供一个可调用的方法,以处理业务逻辑
作用封装一段数据处理逻辑,计算并返回结果定义这一实例的行为,用于处理业务逻辑
声明位置computed 配置项中methods 配置项中
访问方式作为属性,直接使用{{ 计算属性名 }}this.计算属性作为方法,需要调用{{ 方法名() }}this.方法名()
自动依赖追踪是(只有在依赖的数据变化时才会重新计算)否(每次调用都会执行函数,无论依赖的数据是否变化)
缓存计算结果会被缓存,性能更高不会缓存,每次调用都会重新计算
返回值直接返回计算结果直接返回计算结果
特定场景适用性高频更新、需要对依赖数据变化反应的情况适合需要执行不定逻辑的情况
可写性默认是只读的,如果需要修改需完整定义 getter 和 setter可以在方法中进行参数传递和逻辑处理

缓存特性
计算属性会缓存计算结果,后续使用时会直接读取缓存。当其依赖的响应式数据发生变化时,计算属性会进行重新计算并更新缓存。即使模板频繁渲染,计算属性也能够避免重复计算,从而大大提升性能。

【示例】
computed计算属性

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>table {border: 1px solid #000;text-align: center;width: 300px;}th,td {border: 1px solid #000;}h3 {position: relative;}span {position: absolute;left: 145px;top: -4px;width: 16px;height: 16px;color: white;font-size: 12px;text-align: center;border-radius: 50%;background-color: #e63f32;}</style>
</head>
<body><div id="app"><h3>礼物清单🛒<span>{{ totalCount }}</span></h3><h3>礼物清单🛒<span>{{ totalCount }}</span></h3><h3>礼物清单🛒<span>{{ totalCount }}</span></h3><table><tr><th>名字</th><th>数量</th></tr><tr v-for="(item, index) in list" :key="item.id"><td>{{ item.name }}</td><td>{{ item.num }}个</td></tr></table><p>礼物总数:{{ totalCount }} 个</p></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {// 现有的数据list: [{ id: 1, name: '篮球', num: 3 },{ id: 2, name: '玩具', num: 2 },{ id: 3, name: '铅笔', num: 5 },]},computed: {totalCount () {console.log('computed计算属性执行了')let total = this.list.reduce((sum, item) => sum + item.num, 0)return total}}})</script>
</body>
</html>

运行结果:
computed计算属性执行了”在控制台打印了一次
在这里插入图片描述

【分析】

  • 依赖追踪:totalCount 是一个计算属性Vue 会自动追踪它所依赖的数据。在这个例子中,totalCount 依赖于 this.list
  • 缓存特性: 计算属性会在初次计算后缓存其结果。它会在依赖的数据没有变化的情况下,避免重复计算。由于在页面渲染时 totalCount 常量只会被计算一次,因此 “computed计算属性执行了” 只打印了一次。
  • 重新计算: 只有在 list 数据发生变化时,计算属性才会重新计算并更新其缓存值。

②methods计算方法


<body><div id="app"><h3>礼物清单🛒<span>{{ totalCount() }}</span></h3><h3>礼物清单🛒<span>{{ totalCount() }}</span></h3><h3>礼物清单🛒<span>{{ totalCount() }}</span></h3><table><tr><th>名字</th><th>数量</th></tr><tr v-for="(item, index) in list" :key="item.id"><td>{{ item.name }}</td><td>{{ item.num }}个</td></tr></table><p>礼物总数:{{ totalCount() }} 个</p></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {// 现有的数据list: [{ id: 1, name: '篮球', num: 3 },{ id: 2, name: '玩具', num: 2 },{ id: 3, name: '铅笔', num: 5 },]},methods:{totalCount () {console.log('methods方法执行了')let total = this.list.reduce((sum, item) => sum + item.num, 0)return total}}})</script>
</body>

运行结果:
“methods方法执行了”在控制台打印了四次
在这里插入图片描述

【分析】

  • 直接调用:totalCount() 是一个方法。每次模板对它进行访问时,都会执行这个方法。
  • 调用次数:totalCount() 被调用了四次。
  • 多次打印:每次渲染时,不管 list 是否变化,totalCount() 方法都被重新调用,从而打印 “methods方法执行了” 四次。

三、完整写法

计算属性默认的简写,只能读取访问,不能 “修改”。如果要 “修改” , 需要写计算属性的完整写法。
在这里插入图片描述

【示例】

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div id="app">姓:<input type="text" v-model="firstName"><br>名:<input type="text" v-model="lastName"><br><p>姓名:{{fullName}}</p><button @click="changeName">修改姓名</button></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>const app = new Vue({el: '#app',data:{firstName:'吕',lastName:'布'},computed: {// 默认简写→获取/* fullName(){return this.firstName+this.lastName} */// 完整写法→获取+设置fullName:{/* 当fullName计算属性被获取求值时,执行 get 方法(有缓存会优先获取缓存)将返回值作为求值的结果 */get(){return this.firstName+this.lastName},/* 当fullName计算属性被修改赋值时,执行 set 方法修改的值会被传递给set方法的形参slice 方法:用来返回一个新的数组或字符串,包含原始数组或字符串的一部分。slice(start, end);start:开始索引(可选):表示从哪个位置开始提取子字符串(包含该位置的字符)。end:结束索引(可选):表示提取到哪个位置(不包含该位置的字符)。*/set(value){this.firstName=value.slice(0,1)this.lastName=value.slice(1)}}},methods: {changeName(){this.fullName='刘备'}}})</script>
</body>
</html>

运行结果:
在这里插入图片描述
点击“修改姓名”后:
在这里插入图片描述
【案例——成绩管理】
根据所学知识实现以下效果:
在这里插入图片描述

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><link rel="stylesheet" href="./styles/index.css" /><title>成绩管理</title></head><body><div id="app" class="score-case"><div class="table"><table><thead><tr><th>编号</th><th>科目</th><th>成绩</th><th>操作</th></tr></thead><tbody v-if="list.length>0"><tr v-for="(item,index) in list" :key="item.id"><td>{{index+1}}</td><td>{{item.subject}}</td><td :class="{red:item.score<60}">{{item.score}}</td><td><a href="#" @click="del(item.id)">删除</a></td></tr></tbody><tbody v-else><tr><td colspan="5"><span class="none">暂无数据</span></td></tr></tbody><tfoot><tr><td colspan="5"><span>总分:{{totalScore}}</span><span style="margin-left: 50px">平均分:{{averageScore}}</span></td></tr></tfoot></table></div><div class="form"><div class="form-item"><div class="label">科目:</div><div class="input"><inputtype="text"placeholder="请输入科目"v-model.trim="subject"/></div></div><div class="form-item"><div class="label">分数:</div><div class="input"><inputtype="text"placeholder="请输入分数"v-model.number="score"/></div></div><div class="form-item"><div class="label"></div><div class="input"><button class="submit" @click="add()">添加</button></div></div></div></div><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {list: [{ id: 1, subject: '语文', score: 20 },{ id: 7, subject: '数学', score: 99 },{ id: 12, subject: '英语', score: 70 },],subject: '',score: ''},methods: {/* filter方法:用于创建一个新数组,包含所有通过测试的元素测试条件是每个元素的 id 不等于要删除的 id */del(id){this.list=this.list.filter(item=>item.id!==id)},/* add方法:负责在列表的开头添加一条新的成绩记录 */add(){if(!this.subject){alert("请输入科目")return}if(typeof this.score!=='number'){alert("请输入正确的成绩")return}/* unshift方法:用于在数组的开头添加一个或多个元素,并返回新数组的长度id: 使用当前时间戳作为新成绩的唯一标识+new Date():将当前日期转换为毫秒数,确保每条记录的 id 是唯一的 */this.list.unshift({id:+new Date(),subject:this.subject,score:this.score})this.subject=''this.score=''}},computed:{/* reduce方法:用于将数组中的所有元素汇总为一个单一的值(sum, item) => sum + item.score: 一个累加函数 */totalScore(){return this.list.reduce((sum,item)=>sum+item.score,0)},averageScore(){if(this.list.length===0){return 0}/* .toFixed()方法:用于将一个数字格式化为字符串,保留指定的小数位数 */return (this.totalScore/this.list.length).toFixed(2)}}})</script></body>
</html>

运行结果:
在这里插入图片描述
删除语文成绩后:
在这里插入图片描述
添加美术成绩后:
在这里插入图片描述
删除全部成绩后:
在这里插入图片描述


http://www.ppmy.cn/news/1517300.html

相关文章

内存管理篇-14kmalloc机制实现分析

引入这个kmalloc的目的&#xff0c;是因为前面的slab接口太过于复杂&#xff0c;因此需要一个全新的封装kmalloc接口&#xff0c;内存申请编程接口实现。kmalloc底层起始也是基于slab缓存实现的。 1.kmalloc 调用流程 参数解析: 解析 gfp_mask 参数&#xff0c;确定分配时是否…

2024117读书笔记|《李煜词(果麦经典)》——一壶酒,一竿身,快活如侬有几人?一片芳心千万绪,人间没个安排处

2024117读书笔记|《李煜词&#xff08;果麦经典&#xff09;》——一壶酒&#xff0c;一竿身&#xff0c;快活如侬有几人&#xff1f;一片芳心千万绪&#xff0c;人间没个安排处 《李煜词&#xff08;果麦经典&#xff09;》李煜的词很美&#xff0c;插图也不错&#xff0c;很值…

25届应届网安面试,默认页面信息泄露

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

模拟实现STL中的unordered_map和unordered_set

目录 1.unordered_map和unordered_set简介 2.unordered_map和unordered_set设计图 3.迭代器的设计 4.哈希表的设计 5.my_unordered_map和my_unordered_set代码 1.unordered_map和unordered_set简介 unordered_map和unordered_set的使用非常类似于map和set&#xff0c;两…

GATK ReadsPathDataSource类介绍

GATK&#xff08;Genome Analysis Toolkit&#xff09;是一个广泛使用的基因组分析工具包&#xff0c;它的核心库之一是htsjdk&#xff0c;用于处理高通量测序数据。在GATK中&#xff0c;ReadsPathDataSource类是负责管理和提供读取高通量测序数据文件&#xff08;如BAM、SAM、…

android selinux报avc denied权限和编译报neverallow解决方案

avc: denied { read } for name“present” dev“sysfs” ino42693 scontextu:r:hal_health_default:s0 tcontextu:object_r:sysfs:s0 tclassfile permissive1 denied {xxx}: 表示缺少什么权限 scontext:表示谁缺少权限 tcontext:表示对那些文件缺少权限&#xff1a; tclass&am…

华为云 x 容联云|828企业节,助推中国数智产业实力再升级

2024年8月27日&#xff0c;华为第三届828 B2B企业节在2024中国国际大数据产业博览会上正式开幕。 828 B2B企业节是全国首个基于数字化赋能的企业节&#xff0c;由华为联合上万家生态伙伴共同发起&#xff0c;旨在为广大企业尤其是中小企业搭建数字化创新发展平台&#xff0c;融…

关于Arrays.asList返回List无法新增和删除?

这个是在写项目的时候发现的&#xff0c;然后就分析了一下源码&#xff0c;得其内部原理 复现代码示例&#xff1a; public class ArraysAsList {public static void main(String[] args) {Integer[] array {1, 2, 3, 4, 5};List<Integer> list Arrays.asList(array);…