1.计算属性
2.监视属性
3.计算属性与监视属性之间的关系
一.计算属性
- 定义:要用的属性不存在,要通过已有属性计算得来
- 原理:底层借助了Object.defineproperty方法提供的getter和setter
- get函数什么时候会执行:初次读取的时候会执行一次; 当依赖的数据发生改变时会被再次调用
- 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
- 计算属性最终会出现在vm上,直接读取使用即可
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时所依赖的数据发生改变
- 使用computed配置来实现,在模板中可以直接使用
<div id="root">姓:<input type="text" v-model="firstName"><br><br>名:<input type="text" v-model="lastName"><br><br>全名:<span>{{fullName}}</span></div><script type="text/javascript">const vm = new Vue({el:'#root',data: {firstName:'张',lastName:'三'},computed: {fullName:{get() {return this.firstName + '-' + this.lastName},// 当fullName被修改时调用set(value) {const arr = value.split('-')this.firstName = arr[0]this.lastName = arr[1]}}}})
-
修改输入框中的内容时,下面的计算属性也会跟着变化
9. 如果只考虑读取,不考虑修改的话,可以简写为以下形式
<script type="text/javascript">const vm = new Vue({el:'#root',data: {firstName:'张',lastName:'三'},computed: {// 完整写法// fullName:{// get() {// return this.firstName + '-' + this.lastName// },// set(value) {// const arr = value.split('-')// this.firstName = arr[0]// this.lastName = arr[1]// }// }// 简写形式:只考虑读取,不考虑修改的时候才能使用fullName() {return this.firstName + '-' + this.lastName}}})</script>
二. 监视属性
(1)概念:监视属性是监视data的属性变化,也可以用于监视计算属性
(2)监视属性传的是一个配置对象,监视谁,在watch里面就写谁
(3)监视的属性中必须包含一个handler函数,handler函数有两个参数,分别代表修改前和修改后的值,当监视的属性发生变化时,回调函数自动调用,进行相关操作
(4)也可以对commputed中的属性进行监视
const vm = new Vue({el: '#root',data: {isHot: true},computed: {info () {return this.isHot ? '炎热' : '凉爽'}},methods: {changeWeather () {this.isHot = !this.isHot}},watch: {info: {handler (newValue, oldValue) {console.log('isHot被修改了')console.log(newValue, oldValue)}}}})
(5) immediate属性设置为true就是初始化的时候让handler调一下
(6)监视属性的另外一种写法:通过调用vm.$watch函数实现监视,第一个参数是'isHot', 第二个参数传入的是一个对象,与在vm中声明watch配置项中的对象是一样的
vm.$watch('isHot', {immediate: true,// 什么时候调用handler 当isHot被修改的时候handler (newValue, oldValue) {console.log('isHot被修改了')console.log(newValue, oldValue)}})
(7)深度监视
- Vue中的watch默认不监视对象内部值得改变,只监视一层
- 通过配置deep:true 可以检测对象内部值的改变,实现深度监视(多层监视)
- Vue自身可以检测对象内部值得改变,但是Vue提供的watch默认不可以
- 使用watch时,根据数据的具体结构,决定是否采用深度监视
- 如果不加deep:true的话,handler里面的逻辑是不会执行的
<div id="root"><h3>a的值是{{numbers.a}}</h3><button @click="numbers.a++">点我让a+1</button><hr><h3>b的值是{{numbers.b}}</h3><button @click="numbers.b++">点我让b+1</button></div><script type="text/javascript">const vm = new Vue({el: '#root',data: {isHot: true,numbers: {a: 1,b: 1}},watch: {// 监视多级结构中某个属性的变化numbers: {// 开启深度监视deep: true,handler () {console.log('number改变了')}}}})</script>
(8)如果配置项中只需要handler的时候就可以简写
watch: {// 简写: 配置项中只需要handler的时候就可以简写isHot (newValue, oldValue) {console.log('isHot被修改了', newValue, oldValue)}}// vm的写法 简写:只有handlervm.$watch('isHot', function (newValue, oldValue) {console.log('isHot被修改了', newValue, oldValue)})
三.监视属性和计算属性之间的关系
(1)计算属性computed能完成的功能,watch也能实现
(2)watch能实现的,computed不一定能实现,watch可以进行异步操作, computed靠的是返回值,没有办法实现异步任务, watch里面是直接通过手动修改
(3)两个小原则
- 所有Vue管理的函数,最好写成普通函数,这样this的指向才是vm或者组件实例对象
- 所有不被Vue管理的函数(定时器的回调,ajax的回调函数, promise的回调函数),最好写成箭头函数,这样this的指向才是vm或者组件实例对象
const vm = new Vue({el:'#root',data: {firstName:'张',lastName:'三',fullName:'张-三'},// 能开启异步任务watch: {firstName(val) {setTimeout(()=> {this.fullName = val + '-' + this.lastName}, 1000)},lastName(val) {this.fullName = this.firstName + '-' + val}}})