当前位置: 首页 > news >正文

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.方法名( ) {{ 方法名() }} @事件名=“方法名”

二者的区别

缓存特性(提升性能):

  1. 计算属性会对计算出来的结果缓存,再次使用直接读取缓存,依赖项变化了,会自动重新计算 → 并再次缓存

  2. 而方法却是每次获取值的时候都会重新计算

示例:

使用 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)}}}
  1. deep: true 对复杂类型深度监视

  2. 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 基础学习】

相关文章:

  • 【驱动】RS485收发控制、自动收发电路及波特率限制
  • 介绍一下Lumina-T2X在哪些领域有应用
  • elementui中 表格使用树形数据且固定一列时展开子集移入时背景色不全问题(父级和子级所展示的字段是不一样的时候)
  • Rust后台管理系统Salvo-admin源码编译
  • 基于Fluent和深度学习算法驱动的流体力学计算与应用
  • 5.27周报
  • 【MySQL精通之路】数据类型
  • [转载]同一台电脑同时使用GitHub和GitLab
  • C++:vector基础讲解
  • 【ARMv8/v9 异常模型入门及渐进 10 -- WFI 与 WFE 使用详细介绍 1】
  • linux网卡MAC地址
  • 浅谈,Java当中普通类与抽象类的区别
  • Day47 打家劫舍123
  • 【MySQL精通之路】全文搜索(3)-带查询扩展的全文搜索
  • .DFS.
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • javascript数组去重/查找/插入/删除
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 使用common-codec进行md5加密
  • 消息队列系列二(IOT中消息队列的应用)
  • 用element的upload组件实现多图片上传和压缩
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • 扩展资源服务器解决oauth2 性能瓶颈
  • ​Java基础复习笔记 第16章:网络编程
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • !!Dom4j 学习笔记
  • #php的pecl工具#
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (el-Transfer)操作(不使用 ts):Element-plus 中 Select 组件动态设置 options 值需求的解决过程
  • (Java入门)抽象类,接口,内部类
  • (八)Spring源码解析:Spring MVC
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (六)软件测试分工
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (转)VC++中ondraw在什么时候调用的
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .aanva
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .config、Kconfig、***_defconfig之间的关系和工作原理
  • .gitignore文件设置了忽略但不生效
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .net core 使用js,.net core 使用javascript,在.net core项目中怎么使用javascript
  • .net web项目 调用webService
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .net 设置默认首页
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • :“Failed to access IIS metabase”解决方法