# 一、computed
computed擅长处理的场景:一个数据受多个数据的影响
那么问题来了:什么是一个数据受多个数据影响
看下面的例子:
<body>
<div id="app">
{{price}}
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
count:10,
money:100
},
computed: {
price() {
return this.money*this.count //结果为1000
}
},
})
</script>
</body>
这个例子中我需要计算最终的价钱price并显示到页面中,这个price就相当于我需要计算的这一个数据,而这个price受到count和money的影响,也就是说,count和money的值会影响price最终的值,这就是所谓的一个数据受多个数据影响
我们再来看看这个例子:
<body>
<div id="app">
{{getPrice()}}
<button @click="getPrice">计算</button> <!-- 调用getPrice方法 -->
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
count:10,
money:100
},
methods: {
getPrice() {
console.log("我被重新计算了") //注意这行
return this.count*this.money
}
},
})
</script>
</body>
我们将上面的例子用method方法重新改写,也实现了计算price的值,当多次点击按钮的时候,控制台则会显示
也就是说, 即使getPrice中的计算所依赖的值并没有发生改变,每次调用getPrice方法也会重新打印一次,换句话说,method方法并不支持缓存
接着用computed方法再进行改造一次
<body>
<div id="app">
{{getPrice}}
<button @click="count=10">计算</button>
<!-- 在这里触发点击方法使count赋值(但值不改变,仍为原来的值10)响应computed -->
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
count: 10,
money: 100
},
computed: {
getPrice() {
console.log("我被重新计算了")
return this.count * this.money
}
},
})
</script>
</body>
当多次点击按钮的时候,控制台则会只显示一次我被重新计算了,也就是说,computed支持缓存,只有依赖数据发生改变,才会重新进行计算 ,不支持异步,当computed内有异步操作时无效,无法监听数据的变化,
如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
# 二、watch
watch擅长处理的场景:一个数据影响多个数据
那么问题又来了:什么是一个数据影响多个数据
举个栗子,我们需要实现一个功能,当路由跳转变化的时候,打印上一个路由,和当前的路由
<body>
<div id="app">
<router-link to="/first">first</router-link>
<router-link to="/second">second</router-link>
<router-view></router-view>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js"></script>
<script>
const First = { //创建组件First
template: `
<div>first</div>
`
}
const Second = { //创建组件Second
template: `
<div>second</div>
`
}
const routes = [ //创建路由规则
{ path: '/first', component: First },
{ path: '/second', component: Second }
]
const router = new VueRouter({ //创建VueRouter实例,并把规则挂载到路由
routes
})
const app = new Vue({
el: "#app",
watch: {
"$route.path":function(newVal,oldVal) {
//在这里newVal代表当前的路由,oldVal代表跳转之前的路由
console.log(newVal,oldVal)
}
},
router //将路由实例挂载都Vue实例上
})
</script>
</body>
可以看到,当我们由first路由跳到second路由的时候,控制台就会打印
在这里,你可以理解为一个数据:$route对象,影响多个数据:路由跳转之前的值,跳转之后的值
其次,watch不支持缓存,数据变,直接会触发相应的操作,但它支持异步,监听的函数接收两个参数,第一个参数是最新的值,第二个参数是输入之前的值,监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数
-
immediate:组件加载立即触发回调函数执行
-
deep: 深度监听
假设有以下代码
<body>
<div id="app">
<p>FullName: {{fullName}}</p>
<p>FirstName: <input type="text" v-model="firstName"></p>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
firstName: 'Dawei',
lastName: 'Lou',
fullName: ''
},
watch: {
firstName(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
}
}
})
</script>
</body>
上面的代码的效果是,当我们输入firstName
后,wacth
监听每次修改变化的新值,然后计算输出fullName
。即firstName
的改变影响了fullName
这里 watch 的一个特点是,最初绑定的时候是不会执行的,要等到 firstName
改变时才执行监听计算。换句话说,当打开页面的时候,{{fullName}}
不会有值,那我们想要一开始就让他最初绑定的时候就执行改怎么办呢?我们需要修改一下我们的 watch 写法,修改过后的 watch 代码如下:
watch: {
firstName: {
handler(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
},
// 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
immediate: true
}
}
# 三、总结
1.computed擅长处理的场景:一个数据受多个数据影响,computed支持缓存,只有依赖数据发生改变,才会重新进行计算 ,不支持异步,当computed内有异步操作时无效,无法监听数据的变化, 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
2.watch擅长处理的场景:一个数据影响多个数据,不支持缓存,数据变,直接会触发相应的操作,但它支持异步,监听的函数接收两个参数,第一个参数是最新的值,第二个参数是输入之前的值,监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数
-
immediate:组件加载立即触发回调函数执行
-
deep: 深度监听
当需要在数据变化时执行异步或开销较大的操作时,使用watch是最有用的。这是和computed最大的区别