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的写法 简写:只有handler
vm.$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
}
}
})