一、computed与watch
在之前的练习中本人碰到computed来监听某个数据变化。我们都知道computed与watch都是可以监听数据变化,但具体要怎么区别它们呢?
1.1 watch
1.1.1 watch的简单执行
<template>
<div class="stylebg">
<div class="mt22">
watch的运用
</div>
<div>
姓:<el-input v-model="firstName"></el-input>
</div>
<div>
名:<el-input v-model="secondName"></el-input>
</div>
<div>
{{fullName}}
</div>
</div>
</template>
<script>
export default {
data(){
return{
firstName:'1',
secondName:'2',
fullName:''
}
},
watch:{
firstName(fValue){
console.log('执行了watch')
this.fullName = fValue + this.secondName
},
secondName(sValue){
this.fullName = this.firstName + sValue
},
}
}
</script>
<style scoped>
.mt22{
margin:22px 0;
}
</style>
运行截图
1.2.1 watch的特点
根据上述代码我们可以总结出watch以下5种特点:
- 监听一个数据,一个属性影响多个属性
- 不使用return返回
- 第一次加载不会监听watch里的属性名
- 支持异步操作,既可以监听到异步
- 不支持缓存
1.3.1 watch的首次加载
从上述1.2的代码运行中,可以得出我们第一次加载页面的时候,watch是不会监听watch里的属性名,那么有没有一种方法是可以接触这种限制呢?在1.3.1会进一步的说明
1.3.1.1 watch如何实现首次加载
我们把1.2的代码进一步地改进,需要在属性名里面定义immediate:true的相关属性,再把需要所赋的最新值,写入内部属性的方法handler( )中,即可在第一次加载监听watch的某个属性名。
<template>
<div class="stylebg">
<div class="mt22">
watch的运用
</div>
<div>
姓:<el-input v-model="firstName"></el-input>
</div>
<div>
名:<el-input v-model="secondName"></el-input>
</div>
<div>
{{fullName}}
</div>
</div>
</template>
<script>
export default {
data(){
return{
firstName:'1',
secondName:'2',
fullName:'',
}
},
watch:{
firstName: {
// 监听数据
handler(fValue) {
console.log('执行了watch')
this.fullName = fValue + this.secondName
},
deep: true, // 深度监听
immediate:true, //当 watch 一个变量的时候,初始化时并不会执行你需要在created的时候手动调用一次。添加immediate属性,这样初始化的时候也会触发
},
secondName(sValue){
this.fullName = this.firstName + sValue
}
}
}
</script>
<style scoped>
.mt22{
margin:22px 0;
}
</style>
运行截图
从运行截图中我们可以看出首次加载页面的时候会执行firstName属性名中的内部代码(从控制台打印出‘执行了watch’的字符串以及界面显示了fullname的字符串可以看出)
2.1 computed
2.1.1 computed的简单运行
<template>
<div class="stylebg">
<div class="mt22">
computed的运用
</div>
<div>
姓:<el-input v-model="firstName2"></el-input>
</div>
<div>
名:<el-input v-model="secondName2"></el-input>
</div>
<div>
{{fullName2}}
</div>
</div>
</template>
<script>
export default {
data(){
return{
firstName2:'1',
secondName2:'2',
// fullName2:''
}
},
computed:{
fullName2(){
console.log('执行了computed')
return this.firstName2 + this.secondName2
}
},
}
</script>
<style scoped>
.mt22{
margin:22px 0;
}
</style>
运行截图
2.2.1 computed的特点
根据上述代码我们可以总结出computed以下5种特点:
- 监听多个数据,多个属性影响一个属性
- 必须使用return返回
- 第一次加载会监听computed里的属性名
- 无法支持异步操作,既不能监听到异步操作里面的数据变化
- 支持缓存,可以避免每次取值时需要重新计算。
2.2.2 computed中设置属性名问题
在编写代码中遇到一个问题,因为computed在运行时是会return把计算的数值直接返回到变量fullName2中,而在data中又同时有fullName2的空字符串,执行代码的时候会发生错误,那么为什么会发生这种错误呢?主要是牵扯到属性名重命名的问题。
2.2.2.1 为什么在data与compted中的属性不能重定义,会报错?
在执行把数据挂在vm实例中会参考下述的vue源码
function initState (vm) {
vm._watchers = [];
var opts = vm.$options;
if (opts.props) { initProps(vm, opts.props); }
if (opts.methods) { initMethods(vm, opts.methods); }
if (opts.data) {
initData(vm);
} else {
observe(vm._data = {}, true /* asRootData */);
}
if (opts.computed) { initComputed(vm, opts.computed); }
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch);
}
}
可以看出上述,代码会把props等通过方法挂载在vm实例上面,执行顺序为props→methods→data→computed→watch。所以若属性名相同的话,后面的值会把前面的值覆盖。在实际运行中会直接抛出属性名重命名的错误。
在书写代码需要避免属性名重复书写。
二、computed与watch的区别
在经过第一章computed与watch的运行介绍,可以列出它们的区别:
watch | computed |
---|---|
监听一个数据,一个属性影响多个属性 | 监听多个数据,多个属性影响一个属性 |
不使用return返回 | 必须使用return返回 |
第一次加载不会监听watch里的属性名(未设置immediate:true情况下) | 第一次加载会监听computed里的属性名 |
支持异步操作,既可以监听到异步 | 无法支持异步操作,既不能监听到异步操作里面的数据变化 |
不支持缓存 | 支持缓存,可以避免每次取值时需要重新计算。 |
三、computed与watch一般会使用到的场景
watch: 如需要执行异步操作或者开销比较大的场景,搜索框输入一个字符串会调用API去动态获取相应的数据列表。
computed: 如购物车勾选多件商品,此时勾选每件商品的价钱属性影响总价的属性。