Chapter 05 计算属性

news2024/12/26 5:06:47

欢迎大家订阅【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 进行求和→reduce
          let 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">
            <input
              type="text"
              placeholder="请输入科目"
              v-model.trim="subject"
            />
          </div>
        </div>
        <div class="form-item">
          <div class="label">分数:</div>
          <div class="input">
            <input
              type="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.coloradmin.cn/o/2083324.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

笔记整理—uboot启动过程(7)malloc初始化与内存环境变量

上一章说到了env环境变量并对前两章有关init_sequence部分做了总结&#xff0c;这一章将要对uboot部分的malloc初始化以及内存环境变量进行相关的说明。 mem_malloc_init是用于初始化uboot堆管理器的。自己维护了一段内存&#xff0c;就可用进行malloc和free的操作了。那么这个…

Mac/Linux系统matplotlib中文支持问题

背景 matplotlib是python中最常用的数据可视化分析工具&#xff0c;Mac和Linux系统无中文字体&#xff0c;不支持中文显示&#xff08;希望后续可以改进&#xff09;&#xff0c;需要进行字体的下载和设置才能解决。笔者经过实践&#xff0c;发现Mac系统和Linux系统解决方案略…

数据结构算法基础-单链表的新建(头插法、尾插法)

1.头插法 2.尾插法 3.代码及运行结果 设输入的值为&#xff1a;3 4 5 6 7&#xff08;到9999终止读值&#xff09; #include <stdio.h> #include <stdlib.h> typedef int ElemType;typedef struct LNode{ElemType data;struct LNode *next; }LNode,*LinkList;LinkL…

02 vue3之ref全局桶

ref 接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property&#xff0c;指向该内部值。 <template><div class"">Ref:{{ name.a }}</div><button click"change()">change</button> </te…

如何用Java构建学生档案管理系统:实现学生信息的高效管理

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Mybatis缓存、java反射(精简秒懂版)

目录 一、缓存 1.mybatis一级缓存 2.mybatis二级缓存 开启二级缓存 二、Java反射机制概念 1.Java反射概念 2.Java反射相关api 三、Java反射相关类 1.Class类&#xff08;反射基础&#xff09; &#xff08;1&#xff09;Object类中的getClass方法&#xff1a;适用于通过对…

sdk监控平台

监控平台实现方案 监测网页加载时长是关注的是以下5个过程&#xff1a; 1.重定向时间&#xff1a;获取此网页前重定向所花费的时间 2.DNS域名查找时间&#xff1a;查找此网页的DNS所花费的时间 3.TCP服务器连接时间&#xff1a;用户连接到您的服务器所需的时间 4.服务器响应…

基于文心智能体平台打造的德语学习助手

德语学习助手&#xff1a;您的智能德语语言学专家 在学习德语的道路上&#xff0c;是否曾遇到过这样的困扰&#xff1a;不知道自己的德语水平如何&#xff1f;学习过程中缺乏系统的计划&#xff1f;在日常交流中总是担心表达不准确&#xff1f;或者在面对德语文本时&#xff0c…

[深度学习] 时间序列分析工具TSLiB库使用指北

TSLiB是一个为深度学习时间序列分析量身打造的开源仓库。它提供了多种深度时间序列模型的统一实现&#xff0c;方便研究人员评估现有模型或开发定制模型。TSLiB涵盖了长时预测&#xff08;Long-term forecasting&#xff09;、短时预测&#xff08;Short-term forecasting&…

【力扣】划分为k个相等的子集

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 给定一个整数数组 …

Learn OpenGL In Qt之系列简介

竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~ 个人主页&#xff1a; rainInSunny | 个人专栏&#xff1a; C那些事儿、 Learn OpenGL In Qt 文章目录 传送门写在前面为什么是OpenGL和Qt能学到什么能做点什么国漫女神炫酷进度冷酷机器人 传送门 待更新 写在前面 本博客系列将带领读…

Vue——初识vue

目录 1.浏览器控制台报错 2.Vue入门 3.Vue模版语法 4.数据绑定 5.el与data的两种写法 总结 本系列属于纯干货系列&#xff0c;我们也不多说&#xff0c;直接上干货。 1.浏览器控制台报错 GET http://127.0.0.1:5500/favicon.ico 404 (Not Found) 具体如下图 这是为什么…

自己动手写CPU_step5_移动指令

移动操作指令 define EXE_MOVN 6b001011 //不等于0转移 if rt ! 0 then rs -> rd define EXE_MOVZ 6b001010 //等于0转移 if rt 0 then rs -> rd define EXE_MFHI 6b010000 // hi -> rd define EXE_MFLO 6b010010 // lo…

一步迅速了解Spring框架的几个特点

一&#xff0c;特点1&#xff1a;IOC(控制反转) 1&#xff0c;IOC是什么 反转控制”(Inverse of Control) 不是什么技术&#xff0c;而是一种设计思想&#xff0c;就是将原本在程序中手动创建对象的控制权&#xff0c;交由 Spring 框架来管理 2&#xff0c;IOC的作用 IOC 容器…

tensor core实现矩阵乘法的详细解读

之前关于tensor core的介绍可以参考链接添加链接描述 基础的tensor core实现C=AB的代码可以参考下面这段内容: 上面代码的几个注意事项: 首先是加载mma.h头文件,这个是包含wmma模板类的头文件。 其次是设置的WMMA_M=16,WMMA_N=16,WMMA_K=8,这三个参数的表示的意思是,对于…

乐凡三防:工业界的硬核产品——重新定义三防平板的极限

在工业4.0的浪潮中&#xff0c;科技与制造业的深度融合催生了一系列高性能、高耐用的智能产品。乐凡三防平板&#xff0c;作为工业界的新宠&#xff0c;正以其卓越的防护性能和强大的功能&#xff0c;重新定义了三防平板的极限&#xff0c;成为硬核科技的代表。 硬核防护&#…

Marching Cubes 算法三探

Marching Cubes 算法再探 CUDA SamplesMarchingCubesworkflowCodedata structurecomputeIsosurfacelaunch_classifyVoxelclassifyVoxel ThrustScanWrapperlaunch_compactVoxelscompactVoxels launch_generateTriangles2generateTriangles2 improvements 初探再探三探&#xff0…

翻译软件推荐:有道翻译及其他选择!

一款好的翻译软件不仅能帮助我们跨越语言障碍&#xff0c;还能提升我们的工作效率。今天&#xff0c;我将为大家深入介绍几款亲测好用的翻译工具&#xff1a;福昕在线翻译、福昕翻译客户端、海鲸AI翻译以及有道翻译。 福昕在线翻译 链接&#xff1a; https://fanyi.pdf365.cn…

write your own xx-starter【1】

在springboot 中&#xff0c;我们加入例如mybatis-spring-boot-starter&#xff0c;接着在application.yml配置数据库信息&#xff0c;就可以使用mybatis了&#xff0c;无需我们手动进行配置 这就是springboot威力&#xff0c;那么他是如何实现的呢&#xff1f;简单来说类似于…

Java面向接口编程—习题

Java面向接口编程—习题 Java面向接口编程—习题 Java面向接口编程—习题需求实现思路具体步骤1.步骤一:创建接口2.步骤2&#xff1a;创建接口的实现类3.步骤3&#xff1a;创建一个厂商4.步骤四&#xff1a;创建测试类 需求 说明采用面向接口编程思想组装一台计算机计算机的主…