一、计算属性computed
概念:处理数据用来解决代码的冗余
用法:当数据需要通过计算才能得到比如我们求商品的总和与全选功能
计算属性语法:
①一定要在vue实例的对象computed中声明一个函数
②这个函数的返回值return就是计算属性的属性值
特殊的机制:缓存机制(提高性能)
(1)计算属性在第一次使用时,会执行一次函数体,之后就会将返回值缓存起来
(2)下一次使用计算属性的时候,不会执行这个函数,而是直接从缓存中读取
(3)只有当计算属性中的数据发生变化时,这个函数才会重新执行一次
写法:有两种
①默认get()方法,仅是获取值
语法格式:
computed:{ 变量名(){ return this.//一大堆需要计算的数据比如翻转数组 } }
看下面这个例子:(大家可以下直接cv到自己新的html中,我的vue引入是在线的)
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- 导包 --> <!-- <script src="./vue.js"></script> --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <p></p> <!-- 翻转字符串 --> <p> {{ msg.split('').reverse().join('') }}</p> <p> {{revMsg}}</p> <p> {{revMsg}}</p> </div> ` <script> let app = new Vue({ el: '#app', data: { msg: '我爱敲代码', }, computed:{ revMsg(){ console.log(1); return this.msg.split('').reverse().join('') } } }) </script> </body> </html>
上述代码实现的效果见下图
看这个例子,我们定义了一个 resMsg 属性计算方法,并通过将字符串分隔(split()方法)此时已经成为了数组 [ "我", "爱", "敲", "代", "码" ],再翻转下,用字符转拼接作return的返回值给resMsg属性,这样我们就可以配合我们的插值表达式进行解析变量了。
我们还发现了,这样写实现了我们想要的效果,减少了代码的冗余并且可以发现我们的resMsg调用不需要写()直接放进插值表达式就可被解析了。
我们也利用它的特殊机制了,只是调用了一次,之后的调用我们从缓存中获取到。
②不仅仅是获取值,还具有修改属性功能的写法
语法:
computed: { 变量名: { get() { return this.firstName + this.lastName }, // set的形参是get的返回 set(val) { console.log(val); } } }
1. 默认情况下,计算属性只有get方法。只能获取,不能修改。否则程序会报错
2. 如果希望计算属性可以修改,则可以实现set方法
看下面这个例子:(大家可以下直接cv到自己新的html中,我的vue引入是在线的)
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- 导包 --> <!-- <script src="./vue.js"></script> --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <!-- HTML结构 --> <div id="app"> 全选<input type="checkbox" v-model="allCheck" > <ul> <li v-for="(item,index) in list"> <!-- v-model双向绑定 当时单选框(表单元素无条件用v-model!)的时候这个就是选中状态--> <input type="checkbox" v-model="item.select">{{item.name}} <label for=""></label> </li> </ul> </div> <script> /* 1. 默认情况下,计算属性只有get方法。只能获取,不能修改。否则程序会报错 2. 如果希望计算属性可以修改,则可以实现set方法 */ /* 创建vue实例 */ var app = new Vue({ //el:挂载点 el: '#app', //data: 要渲染的数据 data: { active:0, list: [ { name: '前端', select: false }, { name: 'UI', select: false }, { name: 'Java', select: false }, { name: 'php', select: false }, { name: 'python', select: false }, { name: 'c', select: false }, { name: '测试', select: false }, { name: '产品', select: false }, ] }, //计算属性 computed: { allCheck:{ get(){ // every返回是布尔值,一假则假,全真为真 //some 返回的也是布尔值,当有一个元素符合条件的时候返回true return this.list.every(item=>item.select) }, set(val){ console.log(val); this.list.forEach(element => { element.select=val }); } } } }) </script> </body> </html>
下面是上述代码实现的效果图
核心代码:
实现上述例子的思路是:
例子分析:这个例子难点在于怎么通过获取到各个单选框的数据与怎么与全选框进行绑定的。
看到表单项我们获取数据用v-model实现双向绑定。这样我们就可达到修改了之后就可以实时得到反馈
遍历我们的列表将list渲染出来
定义一个计算属性方法 allCheck(){} ,在get() 中开始用every()方法做判断(every方法用于遍历数组,当数组元素都是true的时候返回true,否则返回false)用于小选控制全选,当我全部选中的时候,return的值就是我们allCheck的属性值。
下面的set()用于全选控制小选(我们的allCheck是绑定在全选框上的),当我们做出改变修改的时候会触发allCheck的set()方法,当我选中全选框的时候,此时的allCheck是true,在set()中作为val的实参传进去了,因此列表每一项都是true选中状态了!!!
二、侦听器
概念:监听data中的某一个数据变化
写法:有两种
①值类型
watch:{ '要侦听的属性名'(newVal,oldVal){ } } 兄弟姐妹们,上个例子(大家可以下直接cv到自己新的html中,我的vue引入是在线的) <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- 导包 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <!-- HTML结构 --> <div id="app"> 用户: <input type="text" placeholder="请输入用户名" v-model="username"><span></span> <br> 密码: <input type="text" placeholder="请输入密码" v-model="password"> </div> <script> /* 创建vue实例 */ let app = new Vue({ //el:挂载点 el: '#app', //data: 要渲染的数据 data: { username: '', password: '' }, methods: { fn() { return setTimeout(() => { console.log("这是异步操作") }, 1000) } }, //侦听器 watch: { // 一个监听器检测检测一项东西,前面新的,后面之前数据 username(newIfo, oldInfo) { console.log('当前值为', `${newIfo}`, '之前值为', `${oldInfo}`); if (newIfo === 'admin') { console.log('当前用户名不可取,请输入其他用户名') this.fn() } } } }) </script> </body> </html>
核心代码:
我们运行下查看效果:
可以看到,当我们username的时候,浏览器是检测到了我们输入的是admin就弹出了相应的提示('当前用户名不可取,请输入其他用户名),同时我们在值类型在写了一个fn()里面是个异步函数也可以被执行,因此侦听属性的值类型可以执行异步操作。
②引用类型
watch:{ data属性(new,old){ deep: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> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <input type="text" v-model="obj.name"> <input type="text" v-model="obj.age"> </div> <script> new Vue({ el: "#app", data: { obj: { name: "初映", age: 22, fn() { return setTimeout(() => { console.log("这是异步操作") }, 1000) } } }, watch: { obj: { deep: true, immediate: false,//当页面加载完成马上调用一次,记录为新值,救值必须删除 handler(newVal, oldVal) { console.log(`新的值为:` + newVal.name, `旧值为:` + oldVal.name); this.obj.fn() }, } }, methods: {} }) </script> </body> </html>
核心代码:
运行结果:
可以看到我们的深度监听,侦听到了引用类型数值发生了改变,我们也是实时侦听到了数据,同时深度侦听也可以支持异步操作。
总结:计算属性与侦听属性的区别:
(1)功能不同,计算属性用于解决模板冗余问题。侦听器侦听data中某一个数据变化
(2)计算属性具有缓存机制,侦听器没有缓存机制
(3)计算属性不支持异步操作,侦听器支持异步操作
(4)计算属性可以给vue新增属性,侦听器是 data中已有属性
(5)计算属性只要使用了就会执行一次,侦听器默认只有第一次改变才会执行
下面是给兄弟姐妹准备好的Xmind图总结: