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

VU2 学习笔记4 计算属性、监视属性

计算属性computed

先写一个小demo,页面上有输入姓和名的地方,先用{{}}、methods实现功能

<body><div id="root">firstName:<input type="text" v-model="firstName"><br />lastName:<input type="text" v-model="lastName"><br />totName:<span>{{firstName}}{{lastName}}</span></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data() {return {firstName: 'c',lastName: 'at',}},})</script>
</body>

如果现在需要实现某个功能,不管firstName和lastName输入几位,都只取前三位、首字母大写。这时候如果都写在{{}}里,相关的逻辑就会过多(都写在{{}}里当然也不会报错,只是可读性比较低)。

一种改进方式,是可以把逻辑写在methods里。

<body><div id="root">firstName:<input type="text" v-model="firstName"><br />lastName:<input type="text" v-model="lastName"><br />totName:<span>{{getTotName()}}</span></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data() {return {firstName: 'caef',lastName: 'atef',}},methods:{getTotName(){let firstData = this.firstName.slice(0,3);firstData = firstData[0]?.toUpperCase() + firstData?.slice(1);let lastData = this.lastName.slice(0,3);lastData = lastData[0]?.toUpperCase() + lastData?.slice(1);return firstData+lastData;}}})</script>
</body>

注意:如果在{{}}里使用vm的methods,需要给函数加括号,否则显示的就是函数本身。

当data数据发生变化时,模版会重新进行解析。方法也会重新进行调用。所以data的变化会反馈在{{}}中。

用计算属性实现:

属性(property):对Vue来说,data配置项里的内容就是属性。

计算属性:通过已经有的属性或方法,进行一系列加工和计算,生成的全新的属性。

需要注意:Vue中data中的数据和计算数据是分开的,使用计算属性计算出的属性,不能在data中重复设置。

计算属性用computed:{}配置。

computed:{

}

computed内部,每个计算属性的配置有多种形式。可以通过属性名:配置对象的格式配置,配置对象内部需要添加get方法,vue会把get方法的返回值赋给计算属性,并把计算属性添加到实例上:

computed:{

        属性名:{

                get(){...}

        }

}

在计算属性内部,如果设置的是普遍函数,this指向vue实例。如果是箭头函数,this指向window。

<body><div id="root">firstName:<input type="text" v-model="firstName"><br />lastName:<input type="text" v-model="lastName"><br />totName:<span>{{getTotName}}</span></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data() {return {firstName: 'caef',lastName: 'atef',}},computed:{getTotName:{get(){let firstData = this.firstName.slice(0,3);firstData = firstData[0]?.toUpperCase() + firstData?.slice(1);let lastData = this.lastName.slice(0,3);lastData = lastData[0]?.toUpperCase() + lastData?.slice(1);return firstData+lastData;}}}})</script>
</body>

对象式配置中,也可以配置set,set不是必须写的,如果计算属性不需要修改,则不需要写set。set在计算属性被修改时调用:

计算属性的另一种形式是函数式

computed:{

        属性名(){

        }

}

对象式是计算属性的完整写法,但是一般情况下,计算属性通常是不被修改的,因此计算属性有一种简写形式:函数形式。需要注意,函数形式默认写的是get,不能写set。

            getTotName: function(){let firstData = this.firstName.slice(0, 3);firstData = firstData[0]?.toUpperCase() + firstData?.slice(1);let lastData = this.lastName.slice(0, 3);lastData = lastData[0]?.toUpperCase() + lastData?.slice(1);return firstData + lastData;}

可以把配置对象直接写成函数,这个函数会被理解为get。这种形式还可以进一步简写:

            computed: {getTotName() {let firstData = this.firstName.slice(0, 3);firstData = firstData[0]?.toUpperCase() + firstData?.slice(1);let lastData = this.lastName.slice(0, 3);lastData = lastData[0]?.toUpperCase() + lastData?.slice(1);return firstData + lastData;}}

计算属性配置后,也会出现在Vue实例上

但计算属性不会被添加到_data中,计算属性是计算完成时,直接添加到实例上。

缓存机制:虽然计算属性是以get的形式读取,但模版解析时,会把属性值缓存下来,后面再调用属性,不会再次get,会使用缓存值。

计算属性什么时候重新计算:一种情况是初次读取属性时,另一种情况是计算属性所依赖的数据发生变化时。计算属性重新计算时,会更新缓存。

与methods相比,methods没有缓存机制,methods被调用几次,就执行几次。

控制台就打印一次getTotName : 

computed底层是借助object.defineproperty实现的。

监视属性watch

watch可以监听某个属性的改变,当属性值改变时,就触发监听事件。

watch的配置形式是watch:{}。

对于想监视的属性,也有两种配置形式,一种是以配置对象的形式:  被监视的属性:{}

watch:{

        被监视的属性:{

        }

}

用配置对象的形式时,可以配置的一些配置项:

handler函数:当被监视的属性发生改变时,handler函数就会被调用。

<body><div id="root"><button @click="changeData">change</button></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data() {return {bol: true,}},watch:{bol:{handler(){console.log('change');}}},methods:{changeData(){this.bol = !this.bol;}}})</script>
</body>

当点击按钮时,修改bol的值,触发bol上设置的监听事件,控制台输出change。

handler函数提供两个参数,是 发生变化后的属性 和 发生变化前的属性:(两个变量的名字可以写成任意的,但为了可读性,一般都写newValue,oldValue相关的)。

换成其他变量名也可以:

immediate:布尔值,默认是false,配置初始化时,监听事件直接被执行一次,不需要属性改变就能被执行一次。

没点按钮之前,监听事件就被执行一次。

深度监测deep:

对于一些嵌套的数据结构,watch监听事件可能并不生效。因为Vue只监视value值整个,也就是如果value是对象,只要value的地址不变化,就不会触发监听,Vue不会关心value对象地址内部的变量有没有变化。

每次参数变化时,彻底替换整个value,就会触发监听事件,但这种方法过于笨重。

配置deep,可以设置默认检测value指向地址内部变量的变化,deep默认值为false,表示不深度监测。

(vue实例是能够监听多层级数据结构变化的,但watch事件默认是检测多层级)

<body><div id="root"><button @click="changeData">change</button></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>let vm = new Vue({el: '#root',data() {return {bol: {cat:1,dog:1,},}},watch:{bol:{//immediate:true,handler(a,b){console.log(`${a} ---- ${b}`);}}},methods: {changeData() {this.bol.cat++;console.log(this.bol.cat);}}})</script>
</body>

点击页面上的按钮时,修改bol.cat的值,点击按钮,cat值会增加,但不会触发bol上的watch事件。

对于对象中的key,直接写bol.cat会报错,因为bol.cat是不合法的key,对象中的key正常是一个字符串,平时直接写变量名,是一种简写形式,而bol.cat不是合法的简写形式,这里可以修改成字符串。

不合法:

合法:

但是对于这种形式,如果变量中有多个嵌套的变量都需要被监测,则需要写多个监听事件,如果变量数量成百上千,每个都写完全是不可能的,更通用的方法是配置深度监测:

watch也可以用vue实例调用

vm.$watch(要监听的属性(字符串格式),配置对象)。

监视不存在的属性时,虽然监视没有意义,但不会报错:

        vm.$watch('cat', {immediate: true,handler(a, b) {console.log(`${a} ---- ${b}`);}})

当监视页面上不存在的属性时,控制台不会报错,甚至还可以执行一次:

简写形式:

如果不需要immediate,也不需要deep,就可以用简写形式,

            watch: {bol(newValue, oldValue) {console.log(`${a} ---- ${b}`);}},

vm.$watch形式也可以简写:

        vm.$watch('bol',function(newValue, oldValue){console.log(`${a} ---- ${b}`);})

如果需要设置immediate或者deep,就不能使用上述简写形式。

watch与computed:

虽然很多功能,好像既可以用watch,也可以用computed来计算,但两者之间还是存在差异的。

对于某些功能,确实是用watch才能实现,用watch可以使用异步任务,因为watch并不需要返回值。对于computed,在使用异步任务时,部分情况下无法返回正确的数值。

对于某些功能,如果用watch和computed都能进行实现,通常情况下用computed更简单。

配置对象里的普通函数和箭头函数:

在配置配置对象时,所有被vue管理的函数,一般应写成普通函数,this指向vm实例或组件实例。对于非vue管理的函数,一般应写成箭头函数,让this指向实例。

以setTimeout为例,setTimeout是非vue管理的函数,到了定时的时间,不是vue调的回调函数,而是js引擎调的。在需要使用定时器的情况下,如果内部的回调函数是普通函数,this不会指向实例,一般会指向window。当回调函数返回一个值时,返回值不会被交到setTimeout外面。也不能用回调函数指定vue方法的返回值。

http://www.lryc.cn/news/597387.html

相关文章:

  • 北京互联网公司面试题精华解析
  • 计算机网络学习----Https协议
  • 直接偏好优化(DPO):原理、演进与大模型对齐新范式
  • python-82-基于ORM操作数据库(一)简单模型CRUD
  • UniappDay01
  • JavaWeb笔记12
  • MySQL深度理解-深入理解MySQL索引底层数据结构与算法
  • 容联云携手信通院,启动“智能体服务生态共创计划”
  • 华为云ELB(弹性负载均衡)持续报异常
  • 2025年Zigbee技术白皮书:全球物联网无线通信的关键创新
  • HF86611_VC1/HF86611Q_VC1:多通道USB HiFi音频解码器固件技术解析
  • 【自动化运维神器Ansible】深入解析Ansible Host-Pattern:精准控制目标主机的艺术
  • .Net core 部署到IIS出现500.19Internal Server Error 解决方法
  • Ubuntu系统下FFmpeg源码编译安装
  • 内网穿透技术深析:从原理到工具应用的全方位解读,无公网IP本地服务器外网访问实操
  • IGM弧焊机器人气体节约
  • 【数据结构】哈希——位图与布隆过滤器
  • 彩色转灰度的核心逻辑:三种经典方法及原理对比
  • zabbix监控MySQL数据库
  • 企业选择将服务器放在IDC机房托管的优势
  • React+Three.js实现3D场景压力/温度/密度分布可视化
  • Spring Boot与Python的联动:实战案例解析
  • 【智能模型系列】Unity通过访问Ollama调用DeepSeek模型进行本地部署
  • AI产品经理面试宝典第46天:模型评估与Prompt工程核心考点解析
  • Elasticsearch整合:Repository+RestClient双模式查询优化
  • iOS加固工具有哪些?企业级团队协作视角的实战分析
  • Swing-JFrame
  • 实用的逻辑工具——文氏图和真值表,通过这两个工具,可以把复杂的逻辑关系用图形或表格的形式直观地表示出来
  • Docker 启动 PostgreSQL 主从架构:实现数据同步的高效部署指南
  • k8s:docker compose离线部署haborV2.13.1及采用外部的postgresql及redis数据库