计算属性
1. 定义:要用的属性不存在(不需要在 data 中定义),要通过已有属性计算得来
2. 原理:底层借助了 Object.defineproperty 方法提供的 getter 和 setter
3. get 函数什么时候执行?
(1)初次读取时会执行一次
(2)当数据发生改变时会被再次调用
4. 优势:与 methods 实现相比,内部有缓存机制(复用),效率更高,调式方便
5. 备注:
(1)计算属性最终会出现在 vm 上,直接读取使用即可
(2)如果计算属性要被修改,那必须写 set 函数去响应修改,且 set 中要引起计算时依 赖的数据发生改变
下面是一个通过计算属性实现的按下按钮天气发生变化的代码:
<!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="./js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<!-- 点击按钮实现 isHot 的值的取反,默认 isHot 的值是 true -->
<button @click="isHot = !isHot">切换天气</button>
</div>
</body>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el:'#root',
data:{
isHot: true,
},
computed: {
info(){
//如果 isHot 的值为真就返回炎热,为假返回凉爽
return this.isHot ? '炎热': '凉爽'
}
},
})
</script>
</html>
这里用的是计算属性的简写形式,如果要实现的功能是比较复杂的,比如:当表单元素中的姓或名发生改变时,对应的全名也要改变,代码如下:
<!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="./js/vue.js"></script>
</head>
<body>
<div id="root">
姓: <input type="text" v-model="firstName">
<br><br>
名: <input type="text" v-model="lastName">
<br><br>
测试: <input type="text" v-model="x">
<br><br>
全名: <span>{{fullName}}</span>
<br>
</div>
<script>
Vue.config.productionTip = false;
var vm = new Vue({
el:"#root",
data:{
firstName: '张',
la2stName: '三',
x: '99'
},
computed: {
fullName:{
get(){
//当访问fullName时调用
return this.firstName + '-' + this.lastName
},
set(value) {
//当修改fullName时调用
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
</body>
</html>
监视属性
1. 当被监视的属性变化时,回调函数自动调用,进行相关操作
2. 监视的属性必须存在,才能进行监视!
3. 监视的两种写法:
(1)new Vue 时传入 watch 配置
(2)通过 vm.$watch 监视4. watch 里面有一个 handler(newValue,oldValue)函数,用来获取改变前和改变后的值,里面有一个 immediate 属性,默认为 false,改为 true 就是初始化时让 handler 调用一下hander 默认只有当 isHot 发生改变时才会被调用
作用: 比如监听的是一个温度,那么我们就可以利用 handler 函数来计算温差变化
深度监视:
(1)Vue 中的 watch 默认不监测对象内部值的改变(一层)
(2)配置 deep:true 可以检测对象内部值改变(多层)
备注:
(1)Vue 自身可以检测对象内部值的改变,但 Vue 提供的 watch 默认不可以
(2)使用 watch 时根据数据的具体结构,决定是否采用深度监视
监视多级结构中某个属性(这里是 监视 numbers 中 属性 a)的变化:
'numbers.a':{
}
要加 引号监视多级解结构中所有属性的变化:
numbers:{
}
这里我们再用监视属性写一下当改变姓或名对应的全名也随着变化的例子:
<!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="./js/vue.js"></script>
</head>
<body>
<div id="root">
姓: <input type="text" v-model="firstName">
<br><br>
名: <input type="text" v-model="lastName">
<br><br>
全名: <span>{{fullName}}</span>
<br>
</div>
<script>
Vue.config.productionTip = false;
var vm = new Vue({
el:"#root",
data:{
firstName: '张',
lastName: '三',
fullName: '张-三'
},
watch:{
firstName(newValue){
//当姓发生改变时调用
this.fullName = newValue + '-' + this.lastName
},
lastName(newValue) {
//当名发生改变时调用
this.fullName = this.firstName + '-' + newValue
}
}
})
</script>
</body>
</html>
如果我们在监视的时候用不到 immediate 和 deep,只用了 handler() ,那我们可以将其简写为:
监视对象(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
或者
vm.$watch('监视对象',function(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
})
watch 对比 computed
computed 和 watch 之间的区别:
1. computed 能完成的功能, watch 都可以完成
2. watch 能完成的功能, computed 不一定能完成,例如: watch 可以进行异步操作
3. watch 不能监听 computed 计算出的属性,因为 computed 计算属性不改变原值,而 watch 原理是要监听的属性发生改变才能执行
最后
两个重要的小原则:
1. 所被 Vue 管理的函数,最好写成普通函数,这样 this 的指向才是 vm 或 组件实例对象2. 所有不被 Vue 所管理的函数(定时器的回调函数、ajax 的回调函数、Promise的回调函数),最好写成箭头函数,这样 this 的指向才是 vm 或 组件实例对象