Vue.js - 计算属性与侦听器 【0基础向 Vue 基础学习】
文章目录
- 计算属性 computed
- computed 的使用方法
- computed 与 method 的区别
- 计算属性完整写法
- watch 侦听器(监视器)
- 简单写法 → 简单类型数据,直接监视
- 完整写法 → 添加额外配置项
计算属性 computed
computed 的使用方法
**概念:**基于现有的数据,计算出来的新属性。 依赖的数据变化,自动重新计算。
语法:
-
① 声明在 computed 配置项中,一个计算属性对应一个函数
-
② 使用起来和普通属性一样使用 {{ 计算属性名 }}
computed: {计算属性名 () {基于现有数据,编写求值逻辑return 结果}
},
计算属性 → 可以将一段 求值的代码 进行封装
示例:
要求:
通过计算属性来求得获得的礼物的总数

代码:
<!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>礼物总数:{{getSum}} 个</p></div><script src="./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: {getSum() {return this.list.reduce((sum, item) => {return sum + item.num}, 0)}}})</script>
</body></html>
computed 与 method 的区别
computed 计算属性:
**作用:**封装了一段对于数据的处理,求得一个结果。
语法:
-
① 写在 computed 配置项中
-
② 作为属性,直接使用 → this.计算属性 {{ 计算属性 }}
methods 方法:
**作用:**给实例提供一个方法,调用以处理业务逻辑。
语法:
-
① 写在 methods 配置项中
-
② 作为方法,需要调用 → this.方法名( ) {{ 方法名() }} @事件名=“方法名”
二者的区别
缓存特性(提升性能):
-
计算属性会对计算出来的结果缓存,再次使用直接读取缓存,依赖项变化了,会自动重新计算 → 并再次缓存
-
而方法却是每次获取值的时候都会重新计算
示例:
使用 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>?</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><p>礼物总数:{{ totalCount }} 个</p><p>礼物总数:{{ totalCount }} 个</p></div><script src="./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: {f_totalCount() {let total = this.list.reduce((sum, item) => sum + item.num, 0)console.log('methods方式获取值被触发了1次');return total}},computed: {totalCount() {let total = this.list.reduce((sum, item) => sum + item.num, 0)console.log('computed方式获取值被触发了1次');return total}},})</script>
</body></html>

使用 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><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>?</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>礼物总数:{{ f_totalCount() }} 个</p><p>礼物总数:{{ f_totalCount() }} 个</p><p>礼物总数:{{ f_totalCount() }} 个</p></div><script src="./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: {f_totalCount() {let total = this.list.reduce((sum, item) => sum + item.num, 0)console.log('methods方式获取值被触发了1次');return total}},computed: {totalCount() {let total = this.list.reduce((sum, item) => sum + item.num, 0)console.log('computed方式获取值被触发了1次');return total}},})</script>
</body></html>

计算属性完整写法
计算属性默认的简写,只能读取访问,不能 “修改”。
如果要 “修改” → 需要写计算属性的完整写法。

如果修改 computed 的值而其没有 set 函数的话就会报错

例子:

<!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="./vue.js"></script><script>const app = new Vue({el: '#app',data: {firstName: '迪',lastName: '幻'},computed: {fullName: {get() {return this.firstName + this.lastName},set(value) {this.firstName = value.slice(0, 1)this.lastName = value.slice(1)}}},methods: {changeName() {this.fullName = '迪小幻'}}})</script>
</body></html>
**总结:**如果你的计算属性不止想拿来进行读取操作的话,那么加上一个set方法就可以实现数据的读取与改写
watch 侦听器(监视器)
作用:监视数据变化,执行一些 业务逻辑 或 异步操作。
语法:
-
① 简单写法 → 简单类型数据,直接监视
-
② 完整写法 → 添加额外配置项
简单写法 → 简单类型数据,直接监视
data: { words: '苹果',obj: {words: '苹果'}
},
watch: {
// 该方法会在数据变化时,触发执行数据属性名 (newValue, oldValue) {一些业务逻辑 或 异步操作。
},'对象.属性名' (newValue, oldValue) {一些业务逻辑 或 异步操作。}
}
示例:
简单数据类型:

<!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>* {margin: 0;padding: 0;box-sizing: border-box;font-size: 18px;}#app {padding: 10px 20px;}.query {margin: 10px 0;}.box {display: flex;}textarea {width: 300px;height: 160px;font-size: 18px;border: 1px solid #dedede;outline: none;resize: none;padding: 10px;}textarea:hover {border: 1px solid #1589f5;}.transbox {width: 300px;height: 160px;background-color: #f0f0f0;padding: 10px;border: none;}.tip-box {width: 300px;height: 25px;line-height: 25px;display: flex;}.tip-box span {flex: 1;text-align: center;}.query span {font-size: 18px;}.input-wrap {position: relative;}.input-wrap span {position: absolute;right: 15px;bottom: 15px;font-size: 12px;}.input-wrap i {font-size: 20px;font-style: normal;}</style>
</head><body><div id="app"><!-- 条件选择框 --><div class="query"><span>翻译成的语言:</span><select><option value="italy">意大利</option><option value="english">英语</option><option value="german">德语</option></select></div><!-- 翻译框 --><div class="box"><div class="input-wrap"><textarea v-model="words"></textarea><span><i>⌨️</i>文档翻译</span></div><div class="output-wrap"><div class="transbox">mela</div></div></div></div><script src="./vue.js"></script><script src="./axios.js"></script><script>// 接口地址:https://applet-base-api-t.itheima.net/api/translate// 请求方式:get// 请求参数:// (1)words:需要被翻译的文本(必传)// (2)lang: 需要被翻译成的语言(可选)默认值-意大利// -----------------------------------------------const app = new Vue({el: '#app',data: {words: '',// obj: {// words: ''// }},watch: {words(newVal, oldVal) {console.log('words 的值变化了', 'newVal:' + newVal, 'oldVal:' + oldVal);}}})</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" /><title>Document</title><style>* {margin: 0;padding: 0;box-sizing: border-box;font-size: 18px;}#app {padding: 10px 20px;}.query {margin: 10px 0;}.box {display: flex;}textarea {width: 300px;height: 160px;font-size: 18px;border: 1px solid #dedede;outline: none;resize: none;padding: 10px;}textarea:hover {border: 1px solid #1589f5;}.transbox {width: 300px;height: 160px;background-color: #f0f0f0;padding: 10px;border: none;}.tip-box {width: 300px;height: 25px;line-height: 25px;display: flex;}.tip-box span {flex: 1;text-align: center;}.query span {font-size: 18px;}.input-wrap {position: relative;}.input-wrap span {position: absolute;right: 15px;bottom: 15px;font-size: 12px;}.input-wrap i {font-size: 20px;font-style: normal;}</style>
</head><body><div id="app"><!-- 条件选择框 --><div class="query"><span>翻译成的语言:</span><select><option value="italy">意大利</option><option value="english">英语</option><option value="german">德语</option></select></div><!-- 翻译框 --><div class="box"><div class="input-wrap"><textarea v-model="obj.words"></textarea><span><i>⌨️</i>文档翻译</span></div><div class="output-wrap"><div class="transbox">mela</div></div></div></div><script src="./vue.js"></script><script src="./axios.js"></script><script>// 接口地址:https://applet-base-api-t.itheima.net/api/translate// 请求方式:get// 请求参数:// (1)words:需要被翻译的文本(必传)// (2)lang: 需要被翻译成的语言(可选)默认值-意大利// -----------------------------------------------const app = new Vue({el: '#app',data: {words: '',obj: {words: ''}},watch: {words(newVal, oldVal) {console.log('words 的值变化了', 'newVal:' + newVal, 'oldVal:' + oldVal);},'obj.words'(newVal, oldVal) {console.log('obj.words 的值变化了', 'newVal:' + newVal, 'oldVal:' + oldVal);}}})</script>
</body></html>
完整写法 → 添加额外配置项
试想一下会有这样一个情景,如果我们重新选择一门语言的话,那翻译的内容也会发生相应的改变,因此,我们就不能仅仅只检测文本框内容是否发生了改变,还应该检测语言的选择是否发生了变化,因此我们就需要侦听器的完整写法来实现这一功能
侦听器完整写法
data: {obj: {words: '苹果',lang: 'italy'},},watch: {// watch 完整写法数据属性名: {deep: true, // 深度监视immediate: true, // 是否立刻执行一次handlerhandler(newValue) {console.log(newValue)}}}
-
deep: true 对复杂类型深度监视
-
immediate: true 初始化立刻执行一次handler方法
因此我们改良后可以得到以下的代码
<!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>* {margin: 0;padding: 0;box-sizing: border-box;font-size: 18px;}#app {padding: 10px 20px;}.query {margin: 10px 0;}.box {display: flex;}textarea {width: 300px;height: 160px;font-size: 18px;border: 1px solid #dedede;outline: none;resize: none;padding: 10px;}textarea:hover {border: 1px solid #1589f5;}.transbox {width: 300px;height: 160px;background-color: #f0f0f0;padding: 10px;border: none;}.tip-box {width: 300px;height: 25px;line-height: 25px;display: flex;}.tip-box span {flex: 1;text-align: center;}.query span {font-size: 18px;}.input-wrap {position: relative;}.input-wrap span {position: absolute;right: 15px;bottom: 15px;font-size: 12px;}.input-wrap i {font-size: 20px;font-style: normal;}</style>
</head><body><div id="app"><!-- 条件选择框 --><div class="query"><span>翻译成的语言:</span><select v-model="obj.lang"><option value="italy">意大利</option><option value="english">英语</option><option value="german">德语</option></select></div><!-- 翻译框 --><div class="box"><div class="input-wrap"><textarea v-model="obj.words"></textarea><span><i>⌨️</i>文档翻译</span></div><div class="output-wrap"><div class="transbox">mela</div></div></div></div><script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script><script>// 接口地址:https://applet-base-api-t.itheima.net/api/translate// 请求方式:get// 请求参数:// (1)words:需要被翻译的文本(必传)// (2)lang: 需要被翻译成的语言(可选)默认值-意大利// -----------------------------------------------const app = new Vue({el: '#app',data: {words: '',obj: {words: '迪幻',lang: 'italy'}},watch: {obj: {deep: true,immediate: true,handler(newVal, oldVal) {console.log('被修改了', 'newVal:' + newVal, 'oldVal:' + oldVal);}}}})</script>
</body></html>
cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js">
相关文章:
- 本专栏上一章:
Vue.js - Vue 的安装 以及 常用的 Vue 指令 【0基础向 Vue 基础学习】
相关文章:
Vue.js - 计算属性与侦听器 【0基础向 Vue 基础学习】
文章目录 计算属性 computedcomputed 的使用方法computed 与 method 的区别计算属性完整写法 watch 侦听器(监视器)简单写法 → 简单类型数据,直接监视完整写法 → 添加额外配置项 计算属性 computed computed 的使用方法 **概念࿱…...
技术速递|使用 C# 集合表达式重构代码
作者:David Pine 排版:Alan Wang 本文是系列文章的第二篇,该系列文章涵盖了探索 C# 12功能的各种重构场景。在这篇文章中,我们将了解如何使用集合表达式重构代码,我们将学习集合初始化器、各种表达式用法、支持的集合目…...
我的世界开服保姆级教程
前言 Minecraft开服教程 如果你要和朋友联机时,可以选择的方法有这样几种: 局域网联机:优点:简单方便,在MC客户端里自带。缺点:必须在同一局域网内。 有些工具会带有联机功能:优点:一…...
[转载]同一台电脑同时使用GitHub和GitLab
原文地址:https://developer.aliyun.com/article/893801 简介: 工作中我们有时可能会在同一台电脑上使用多个git账号,例如:公司的gitLab账号,个人的gitHub账号。怎样才能在使用gitlab与github时,切换成对应…...
【网络协议】【OSI】一次HTTP请求OSI工作过程详细解析
目录 1. 一次HTTP请求OSI工作过程 1.1 应用层(第7层) 1.2 表示层(第6层) 1.3 会话层(第5层) 1.4 传输层(第4层)...
springboot vue 开源 会员收银系统 (2) 搭建基础框架
前言 完整版演示 前面我们对会员系统https://blog.csdn.net/qq_35238367/article/details/126174288进行了分析 确定了技术选型 和基本的模块 下面我们将从 springboot脚手架开发一套收银系统 使用脚手架的好处 不用编写基础的rabc权限系统将工作量回归业务本身生成代码 便于…...
Java进阶学习笔记26——包装类
包装类: 包装类就是把基本类型的数据包装成对象。 看下API文档: deprecated:极力反对、不赞成的意思。 marked for removal:标识为去除的意思。 自动装箱:基本数据类型可以自动转换成包装类。 自动拆箱:…...
【JavaEE进阶】——要想代码不写死,必须得有spring配置(properties和yml配置文件)
目录 本章目标: 🚩配置文件 🚩SpringBoot配置文件 🎈配置⽂件的格式 🎈 properties 配置⽂件说明 📝properties语法格式 📝读取配置文件 📝properties 缺点分析 dz…...
第十四 Elasticsearch介绍和安装
docker-compose安装 kibana: image: docker.elastic.co/kibana/kibana:7.5.1 container_name: kibana ports: - "5601:5601" environment: ELASTICSEARCH_HOSTS: http://elasticsearch:9200 depends_on: - elasticsearch…...
YOLOv10介绍与推理--图片和视频演示(附源码)
导 读 本文主要对YOLOv10做简单介绍并给出推理图片和视频的步骤演示。 YOLOv10简介 YOLOv10是清华大学的研究人员在Ultralytics Python包的基础上,引入了一种新的实时目标检测方法,解决了YOLO 以前版本在后处理和模型架构方面的不足。通过消除非最大抑…...
Java实验08
实验一 demo.java package q8.demo02;public class demo{public static void main(String[] args) {WindowMenu win new WindowMenu("Hello World",20,30,600,290);} }WindowMenu.java package q8.demo02; import javax.swing.*;public class WindowMenu extends…...
MyBatis复习笔记
3.Mybatis复习 3.1 xml配置 properties:加载配置文件 settings:设置驼峰映射 <settings><setting name"mapUnderscoreToCamelCase" value"true"/> </settings>typeAliases:类型别名设置 #这样在映射…...
HTML的基石:区块标签与小语义标签的深度解析
📚 HTML的基石:区块标签与小语义标签的深度解析 🌐 区块标签:构建网页的框架🏠 <div>:万能的容器📚 <section>、<article>、<aside>:语义化的布局 …...
Windows域控简介
一、Windows 域控概念 Windows 域控即 Active Directory(AD)域控制器,它是 Windows Server 中的一个角色,用于管理网络中的用户帐户、计算机和其他设备。AD 域控制器的功能包括: 用户认证:允许用户通过用…...
项目延期,不要随意加派人手
遇到软件项目出现延期的情况时,不建议随意加派人手。原因如下: 有些任务是不可拆分的,不能拆分为多个并行任务,增加人员不会加快项目进度。新增加人员需要原有人员介绍项目中的技术架构、业务知识,在开发过程中也难免…...
帝国CMS验证码不显示怎么回事呢?
帝国CMS验证码有时候会不显示或打叉,总结自己的解决方法。 1、检查服务器是否开启GD库 测试GD库是否开启的方法:浏览器访问:/e/showkey/index.php,如果出现一堆乱码或报错,证明GD库没有开启,开启即可。 2…...
【必会面试题】Redis 中的 zset数据结构
目录 Redis 中的 zset(sorted set,有序集合)数据结构在底层可以使用两种不同的实现:压缩列表(ziplist) 和 跳跃表(skiplist)。具体使用哪种结构取决于存储元素的数量和大小ÿ…...
括号匹配数据结构
括号匹配是一种数据结构问题,用于检查给定的字符串中的括号是否匹配。例如,对于字符串 "((())())",括号是匹配的,而对于字符串 "())(",括号是不匹配的。 常见的解决括号匹配问题的数据结构是栈。…...
c语言:strcmp
strcmp函数是用于比较两个字符串的库函数,其功能是根据ASCII值逐一对两个字符串进行比较。 语法:strcmp(str1, str2) 返回值: 如果str1等于str2,则返回0。 如果str1小于str2,则返回负数(具体值取决于C…...
传统关系型数据库与hive的区别
数据库和Hive之间存在本质的区别,主要体现在设计目的、数据处理方式、数据存储、查询延迟、数据更新能力、以及适用场景等方面。下面详细阐述它们之间的主要差异: 设计目的与应用场景: 数据库:主要是面向事务处理(OLTP…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
