计算属性 会将数据进行缓存,只在相关响应式依赖数据发生改变时它们才会重新求值。而函数 每次都会执行函数体进行计算。
下面来看一个小demo,分析计算属性和方法函数的区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
姓:<input type="text" v-model="firstName"><br>
名:<input type="text" v-model="lastName"><br>
姓名1(方法):<input type="text" v-model="fullNameByMethods()"><br>
姓名2(计算属性单向):<input type="text" v-model="fullNameByComputed"><br>
</div>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
firstName: 'A',
lastName: 'B',
},
methods: {
//methods 什么时候执行: 页面初始化/相关的数据发生改变
fullNameByMethods: function () {
console.log('方法的fullNameByMethods方法被调用了...')
return this.firstName + this.lastName
}
},
computed: {
//computed 什么时候执行: 页面初始化/相关的数据发生改变
fullNameByComputed: function () {
console.log('计算属性的fullNameByComputed方法被调用了...')
return this.firstName + this.lastName
}
}
})
</script>
</body>
</html>
由上运行观察:
当我们一打开页面/初始化页面的时候,发现计算属性和方法都会调用
我们修改相关响应式依赖数据 ‘姓’ ‘名’时发现计算属性和方法也都会调用
我们再来看一下计算属性缓存的情况
1 首先我们在浏览器控制台上多次输入
vm.fullNameByMethods()
表示调用fullNameByMethods()方法,可以观察到控制台打印输出的相关信息
方法的fullNameByMethods方法被调用了...
"AB"
说明使用方法来获取姓名每次都会调用方法,每次都会执行方法里的逻辑代码。
2 而当我们在浏览器控制台上多次输入
vm.fullNameByComputed
表示调用fullNameByComputed计算属性,可以观察到控制台打印输出的相关信息
“AB”
就很奇怪,调用计算属性,那为什么控制台上就不打印
计算属性的fullNameByComputed方法被调用了...
其实,这就是计算属性缓存的原因,当我们第一次初始化页面的时候,计算属性执行了一次,就会把该计算属性返回的结果进行缓存,缓存结果为“AB”
所以再调用这个计算属性的时候,就不会在控制台上打印计算属性的fullNameByComputed方法被调用了...,也就是再次调用计算属性了,而是直接将缓存当中的数据返回,其实计算属性存在缓存, 多次读取只执行一次getter计算,至于getter方法后面案例提及,其实上面案例的fullNameByComputed默认就是getter方法
但是当我们修改了 相关响应式依赖数据,也就是 ‘姓’ ‘名’ 的时候,计算属性就会再一次执行,一旦再一次执行,就又会把计算属性的结果保存在缓存当中,所以再一次调用的时候,就又从缓存当中获取数据
下面我们再来看一个案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
姓:<input type="text" v-model="firstName"><br>
名:<input type="text" v-model="lastName"><br>
姓名1(计算属性单向):<input type="text" v-model="fullNameByComputed"><br>
姓名2(计算属性双向):<input type="text" v-model="fullNameByGetAndSet"><br>
</div>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
firstName: 'A',
lastName: 'B',
},
computed: {
fullNameByComputed: function () {
return this.firstName + ' ' + this.lastName
},
fullNameByGetAndSet: {
get() {
return this.firstName + ' ' + this.lastName
}
}
},
})
</script>
</body>
</html>
以上案例
计算属性当中fullNameByComputed方法
fullNameByComputed: function () {
return this.firstName + ' ' + this.lastName
},
等价于(默认就是get方法):
fullNameByGetAndSet: {
get() {
return this.firstName + ' ' + this.lastName
}
}
computed 选项内的计算属性fullNameByComputed默认是 getter 函数,所以上面只支持单向绑定,我们改变姓或名,计算属性就会对项目进行同步更新,但是我们修改姓名,控制台就会报错
计算属性(双向绑定)
计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter,setter方法从字面上理解就是设置值,使用setter就能解决修改姓名同步修改姓或名的值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
姓:<input type="text" v-model="firstName"><br>
名:<input type="text" v-model="lastName"><br>
姓名1(计算属性单向):<input type="text" v-model="fullNameByComputed"><br>
姓名2(计算属性双向):<input type="text" v-model="fullNameByGetAndSet"><br>
</div>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
firstName: 'A',
lastName: 'B',
},
computed: {
//计算属性 默认 getter 只支持单向绑定
fullNameByComputed: function () {
return this.firstName + ' ' + this.lastName
},
//指定 getter/setter 双向绑定
fullNameByGetAndSet: {
// 当获取当前属性值时自动调用, 将返回值(根据相关的其它属性数据)作为属性值
get() {
return this.firstName + ' ' + this.lastName
},
// 当属性值发生了改变时自动调用, 监视当前属性值变化, 同步更新相关的其它属性值
set: function (newValue) { //value为更新后的值 也就是姓名
// 更新firstName和lastName
const names = newValue.split(' ') //根据 ‘ ’ 进行拆分
//重新对 姓 和 名 进行赋值
this.firstName = names[0]
this.lastName = names[1]
}
}
},
})
</script>
</body>
</html>
效果:
下面我们同样看一个案例,修改姓或名,更新姓名的demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
姓:<input type="text" v-model="firstName"><br>
名:<input type="text" v-model="lastName"><br>
姓名(监听):<input type="text" v-model="fullNameByWatch"><br>
</div>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
firstName: 'A',
lastName: 'B',
fullNameByWatch:''
},
//监听器方式1:watch选项
watch: {
//对firstName 姓 进行监听
firstName: function(newValue,oldValue) {
console.log('watch监听器执行.....')
console.log(newValue) //新值
console.log(oldValue) //旧值
//更新姓名
this.fullNameByWatch = newValue + this.lastName
}
}
})
//监听器方式2:通过vm对象调用
//第1个参数为监听的属性名 lastName 名 ,第2个回调函数
vm.$watch('lastName',function (newValue) {
//newValue 就是新输入的值
//更新姓名
this.fullNameByWatch = this.firstName + newValue
})
</script>
</body>
</html>
效果演示: