vue2基础语法02——计算属性、方法、侦听器
- 1. 计算属性 computed
- 1.1 为什么要用计算属性
- 1.2 简单例子
- 1.2.1 例子
- 1.2.2 计算属性缓存
- 1.3 计算属性的 setter
- 2. 方法 methods
- 2.1 例子
- 2.2 说明
- 2.3 简单方法替换实现
- 3. 侦听属性 watch
- 3.1 介绍
- 3.2 值的情况
- 3.2.1 对应回调函数
- 3.2.2 方法名
- 3.2.3 包含选项的对象
- 3.2.3.1 选项 immediate
- 3.2.3.2 对于多层级结构——选项 deep
- 3.2.3.2.1 监听整个对象
- 3.2.3.2.1 例子
- 3.2.3.2.1 注意事项
- 3.2.3.2.2 监听对象的某个属性
- 3.2.4 回调数组
- 3.3 使用vm.$watch
- 4. 总结
- 5. 参考
1. 计算属性 computed
1.1 为什么要用计算属性
- 先看下面的例子:
<div id="root"> <h2>狗狗信息_1处:{{dogName}} - {{dogSex==0 ? '女' : '男'}} - {{dogAge}}</h2> <hr> <h2>狗狗信息_1处:{{dogName}} - {{dogSex==0 ? '女' : '男'}} - {{dogAge}}</h2> </div> <script> new Vue({ el: "#root", data: { dogName: "麦兜", dogSex: 0, dogAge: 3, } }) </script>
- 在上面例子中,模板不再是简单的声明式逻辑,虽然模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。
所以,对于任何复杂逻辑,我们应当考虑使用计算属性
。
1.2 简单例子
1.2.1 例子
-
例子如下:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>狗狗信息:{{dogInfoDetail}}</h2> </div> <script> const vm = new Vue({ el: "#root", data: { dogName: "麦兜", dogSex: "女", dogAge: 3, }, computed: { // 计算属性的 getter dogInfoDetail: function(){ // this 指向 vm 实例 return this.dogName + "-" + this.dogSex + "-" + this.dogAge; } } }) </script> </body>
-
这里我们声明了一个计算属性 dogInfoDetail。我们提供的函数将用作 property vm.dogInfoDetail 的 getter 函数。
Vue 知道 vm.dogInfoDetail 依赖于 vm.dogName、vm.dogSex、vm.dogAge,因此当 vm.dogName、vm.dogSex、vm.dogAge 发生改变时,所有依赖 vm.dogInfoDetail 的绑定也会更新。
1.2.2 计算属性缓存
- 计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 计算属性所依赖的属性 还没有发生改变,多次访问计算属性会立即返回之前的计算结果,而不必再次执行函数。
1.3 计算属性的 setter
- 计算属性默认只有 getter,不过在需要时你也可以提供一个 setter。
- 如下例子:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>狗狗信息:{{dogInfoDetail}}</h2> </div> <script> const vm = new Vue({ el: "#root", data: { dogName: "麦兜", dogSex: "女", dogAge: 3, }, computed: { dogInfoDetail: { /* getter 1. 当 dogInfoDetail 被读取时,这里的get方法会被调用,且此get方法的返回值就是计算属性 dogInfoDetail的值 2. 什么时候被调用? 2.1 初次读取 dogInfoDetail 时,后续再读取就是读取的缓存; 2.2 所依赖的数据发生变化时,会重新调用get,重新获取计算属性的值 3. */ get(){ return this.dogName + "-" + this.dogSex + "-" + this.dogAge; }, // setter set: function(newValue){ console.log("newValue:::",newValue); var dogInfo = newValue.split('-') this.dogName = dogInfo[0]; this.dogSex = dogInfo[1]; this.dogAge = dogInfo[dogInfo.length - 1] } } } }); </script> </body>
2. 方法 methods
2.1 例子
- 先看例子:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>狗狗信息_computed:{{dogInfoDetail}}</h2> <hr> <h2>狗狗信息2_methods:{{dogInfoDetail_2()}}</h2> <hr> <button @click="dogInfoDetail_3">点我提示狗狗信息3_methods</button> </div> <script> new Vue({ el: "#root", data: { dogName: "麦兜", dogSex: "女", dogAge: 3, }, computed: { dogInfoDetail: function(){ return this.dogName + "-" + this.dogSex + "-" + this.dogAge; } }, methods: { dogInfoDetail_2: function(){ return this.dogName + "-" + this.dogSex + "-" + this.dogAge; }, dogInfoDetail_3: function(){ console.log('methods……'); var dogInfo = this.dogName + "-" + this.dogSex + "-" + this.dogAge; alert(dogInfo); } }, }) </script> </body>
- 再看效果:
2.2 说明
- methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例。
- 方法不像计算那样可以缓存。
2.3 简单方法替换实现
-
如果方法过于简单,也可以不用定义方法实现,如下直接写语句:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>现在的数字是:{{number}}</h2> <button v-on:click="numberAdd">1_methods:点击数字+1</button> <button @click="number += 1;">2_语句:点击数字+1</button> </div> <script> const vm = new Vue({ el: "#root", data: { number :1, }, methods: { numberAdd(){ this.number++; } }, }) </script> </body>
3. 侦听属性 watch
3.1 介绍
-
类型:{ [key:
string
]: string | Function | Object | Array } -
详细:
一个对象,
键
是需要观察的表达式,值
是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个 property。 -
可以监测 data里的属性,也可以监测 computed 里的计算属性。
3.2 值的情况
3.2.1 对应回调函数
- 测试案例如下:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>你家宠物是狗狗还是猫咪:{{petKindDetail}}</h2> <button v-on:click="petKindCode = (petKindCode == 0) ? 1 : 0;">切换宠物类型</button> </div> <script> const vm = new Vue({ el:"#root", data:{ petKindCode: 0, }, computed:{ petKindDetail: function(){ return this.petKindCode==0 ? "狗狗" : "猫咪"; } }, watch:{ // 1. 值是对应回调函数 'petKindCode': function(newValue,oldValue){ console.log('属性petKindCode被监测前后值变化==》newValue: %s, oldValue: %s', newValue, oldValue) }, // petKindCode 也可以不用引号引起来 // petKindCode: function(newValue,oldValue){ // console.log('属性petKindCode被监测前后值变化==》newValue: %s, oldValue: %s', newValue, oldValue) // }, } }) </script> </body>
- 效果如下:
- 也可以简写成下面形式:
<script> const vm = new Vue({ el:"#root", data:{ petKindCode: 0, }, computed:{ petKindDetail: function(){ return this.petKindCode==0 ? "狗狗" : "猫咪"; } }, watch:{ // 1. 值是对应回调函数 // 'petKindCode': function(newValue,oldValue){ // console.log('属性petKindCode被监测前后值变化==》newValue: %s, oldValue: %s', newValue, oldValue) // }, // petKindCode 也可以不用引号引起来 // petKindCode: function(newValue,oldValue){ // console.log('属性petKindCode被监测前后值变化==》newValue: %s, oldValue: %s', newValue, oldValue) // }, // 简洁写法 petKindCode(newValue,oldValue){ console.log('属性petKindCode被监测前后值变化==》newValue: %s, oldValue: %s', newValue, oldValue) } } }) </script>
3.2.2 方法名
- 测试案例如下:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>你家宠物是狗狗还是猫咪:{{petKindDetail}}</h2> <button v-on:click="petKindCode = (petKindCode == 0) ? 1 : 0;">切换宠物类型</button> </div> <script> const vm = new Vue({ el:"#root", data:{ petKindCode: 0, }, computed:{ petKindDetail: function(){ return this.petKindCode==0 ? "狗狗" : "猫咪"; } }, methods: { // 这里的方法 可以有参数也可以无参数,如果有参数也是被监测属性改变前后的值 // 我这里为了效果,写了有惨 changPetKindCodeMethod(newValue,oldValue){ console.log("被监测属性 petKindCode 的值改变了,执行方法changPetKindCodeMethod..."); console.log('属性petKindCode监视前后值变化===》newValue: %s, oldValue: %s', newValue, oldValue); } }, watch:{ // 2. 值是 方法名 petKindCode: "changPetKindCodeMethod" } }) </script> </body>
- 测试效果如下:
3.2.3 包含选项的对象
3.2.3.1 选项 immediate
- immediate 选项值默认是false,如果设置为true:该回调将会在侦听开始之后被立即调用(即:被监测属性未发生改变、在初始化时或者说页面加载时就调用handler)。
- 例子代码如下:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>你家宠物是狗狗还是猫咪:{{petKindDetail}}</h2> <button v-on:click="petKindCode = (petKindCode == 0) ? 1 : 0;">切换宠物类型</button> </div> <script> const vm = new Vue({ el:"#root", data:{ petKindCode: 0, }, computed:{ petKindDetail: function(){ return this.petKindCode==0 ? "狗狗" : "猫咪"; } }, watch:{ // 3. 值是 包含选项的对象 /* immediate: true 默认是false 如果设置为true:该回调将会在侦听开始之后被立即调用(即:被监测属性未发生改变、在初始化时或者说页面加载时就调用handler) */ petKindCode: { handler: function(newValue,oldValue){ console.log('属性petKindCode监视前后值变化===》newValue: %s, oldValue: %s', newValue, oldValue); }, immediate: true } } }) </script> </body>
- 效果如下:
3.2.3.2 对于多层级结构——选项 deep
3.2.3.2.1 监听整个对象
3.2.3.2.1 例子
- 例子代码如下:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>狗狗信息:{{dog.dogName}} - {{dog.dogAge}} - {{dog.dogWeight}}</h2> <button v-on:click="dog.dogAge++;">狗狗年龄+1</button> <br> <button v-on:click="dog.dogWeight++;">狗狗重量+1</button> </div> <script> const vm = new Vue({ el:"#root", data:{ dog: { dogName: '麦兜', dogAge: 3, dogWeight: 35 } }, watch:{ // 3. 值是 包含选项的对象 /* deep: true 默认是false 如果设置为true:会深度监听属性的变化,即: 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深 */ // 监听整个对象,每个属性值的变化都会执行handler dog: { handler: function(newValue,oldValue){ // 注意:属性值发生变化后,handler执行后获取的 newValue 值和 oldValue 值是一样的 const oldDogJson = JSON.stringify(oldValue); const newDogJson = JSON.stringify(newValue); // console.log(oldValue.dogAge); // console.log(newValue.dogAge); console.log('dog监视前后值变化===》newDogJson: %s, oldDogJson: %s', newDogJson, oldDogJson); }, deep: true } } }) </script> </body>
- 效果如下:
3.2.3.2.1 注意事项
- 上面方式:属性值发生变化后,handler执行后获取的 newValue 值和 oldValue 值是一样的,都是更新后的new值。
3.2.3.2.2 监听对象的某个属性
- 测试代码如下:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>狗狗信息:{{dog.dogName}} - {{dog.dogAge}} - {{dog.dogWeight}}</h2> <button v-on:click="dog.dogAge++;">狗狗年龄+1</button> <br> <button v-on:click="dog.dogWeight++;">狗狗重量+1</button> </div> <script> const vm = new Vue({ el:"#root", data:{ dog: { dogName: '麦兜', dogAge: 3, dogWeight: 35 } }, watch:{ 'dog.dogAge': { handler(newValue,oldValue){ console.log('dogAge监视前后值变化===newValue: %s, oldValue: %s', newValue, oldValue); } } } }) </script> </body>
- 效果如下:
3.2.4 回调数组
- 参考官网:
https://v2.cn.vuejs.org/v2/api/#watch.
3.3 使用vm.$watch
- 通过vm实现监测,语法
vm.$watch( expOrFn, callback, [options] )
- 简单例子:
<body> <script type="text/javascript" src="../js/vue.js"></script> <div id="root"> <h2>你家宠物是狗狗还是猫咪:{{petKindDetail}}</h2> <button v-on:click="petKindCode = (petKindCode == 0) ? 1 : 0;">切换宠物类型</button> </div> <script> const vm = new Vue({ el:"#root", data:{ petKindCode: 0, }, computed:{ petKindDetail: function(){ return this.petKindCode==0 ? "狗狗" : "猫咪"; } }, }); // 这种方式监测,petKindCode 必须用引号引起来 vm.$watch('petKindCode',function(){ console.log('属性petKindCode被监测前后值变化==》newValue: %s, oldValue: %s', newValue, oldValue); }) </script> </body>
- 更多参考:
https://v2.cn.vuejs.org/v2/api/#vm-watch.
4. 总结
- 计算属性可以缓存;methods不能缓存
- 计算属性里不能写定时器,watch里可以写定时器,即:watch可以异步,计算属性不能异步;
5. 参考
-
官网如下:
https://v2.cn.vuejs.org/v2/guide/computed.html.https://v2.cn.vuejs.org/v2/api/#watch.
https://v2.cn.vuejs.org/v2/api/#vm-watch.