一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
前言
在上一篇文章中,讲过了vue的模板语法,今天我们要深入了解一下vue的data/methods/computed/watch的用法。之前的文章中有用过部分内容,通过今天的文章,你将对vue的这些方法有一个更深层次的理解。
data
定义数据的时候,是在vue创建实例的时候去写一个data函数,这个函数在之前的内容中也是经常用到的。在data函数中,会把对应的数据通过return返回给模板,在模板中就可以使用相应的数据。
在之前的内容中,我们知道可以在浏览器控制台通过vm.$data去改变data函数中的数据值,其实在vue里面可以去掉$data也可以改变data函数中的数据值。
<script>
const app = Vue.createApp({
data(){
return {
message: 'Hello World'
}
},
template: "<div>{{message}}</div>"
});
const vm = app.mount('#root');
</script>
methods
在methods中,我们可以定义模板中使用到的各种方法,在之前的内容中,我们也用到过。
<script>
const app = Vue.createApp({
data(){
return {
message: 'Hello World'
}
},
methods: {
handleClick(){
this.message = 'bye'
}
},
template: "<div v-on:click='handleClick'>{{message}}</div>"
});
const vm = app.mount('#root');
</script>
在methods中定义的方法,是有一个this的,这个this就表示vue实例,通过this可以直接修改data方法中的数据值。
如果你想要获取到vue实例的this指向,就不能在methods中定义的方法上使用箭头函数。
methods: {
handleClick: () => {
console.log('通过箭头函数打印data函数中的值:', this.message)
}
},
在浏览器控制台中可以看到,打印出来的是undefined,其实这时候的this指向的并不是vue实例了,而是window,有兴趣的小伙伴可以直接打印this看看返回值。
methods中的函数除了通过v-on绑定的事件去触发,还可以直接在插值表达式中使用。
const app = Vue.createApp({
data(){
return {
message: 'Hello World'
}
},
methods: {
formatString: (string) => {
return string.toUpperCase()
}
},
template: "<div>{{formatString(message)}}</div>"
});
const vm = app.mount('#root');
在浏览器中刷新之后,可以直接渲染出大写字母HELLO WORLD。
computed
<script>
const app = Vue.createApp({
data(){
return {
message: 'Hello World',
count: 2,
price: 4
}
},
template: "<div>{{count * price}}</div>"
});
const vm = app.mount('#root');
</script>
通过上面这个代码可以看出,我们可以在插值表达式中直接去计算data函数中的数据值,但是直接在模板里面去计算,第一是如果计算量太大的话看起来不太美观,第二是没有很好的做到语义化。
理想状态下应该是可以在data函数中定义一个total,然后让total去计算count和price的值。但是data函数中不能直接在函数返回里面调用自身的数据,所以我们可以通过一个计算属性computed来完成这件事。
<script>
const app = Vue.createApp({
data(){
return {
message: 'Hello World',
count: 3,
price: 5
}
},
computed:{
total(){
return this.count * this.price
}
},
template: "<div>{{total}}</div>"
});
const vm = app.mount('#root');
</script>
-
在
computed中定义一个total函数,在函数中返回计算好的数值,就可以在插值表达式中直接使用total,并不需要像methods中的函数一样,去给插值表达式中的total添加一个()代表函数。 -
通过修改
data函数中的数据值,computed中的函数会重新进行计算然后将新的数据值返回到模板中渲染出来。
computed和methods对比
<script>
const app = Vue.createApp({
data(){
return {
message: 'Hello World',
count: 4,
price: 7
}
},
methods: {
getTotal(){
return this.count * this.price
}
},
template: "<div>{{getTotal()}}</div>"
});
const vm = app.mount('#root');
</script>
可能有些人会有疑问,这个计算方式完全可以通过methods中的方法去完成,为什么要使用computed呢?
- 通过下面的例子,你会发现
computed和methods的区别了。
const app = Vue.createApp({
data(){
return {
message: 'Hello World',
count: 4,
price: 7
}
},
computed:{
time(){
return Date.now()
}
},
methods: {
getTime(){
return Date.now()
}
},
template: `<div>
<div>computed - {{message}} - {{time}}</div>
<div>methods - {{message}} - {{getTime()}}</div>
</div>`
});
const vm = app.mount('#root');
我们在computed和methods中都返回当前时间戳,然后我们去浏览器控制台修改message的值,看看这两个之间的具体区别。
通过浏览器输出的内容可以看出,当message值改变之后,computed返回的时间戳是不变的,而methods中的方法返回的时间戳是随着页面数据改变而改变的。
因为当页面重新渲染之后,methods中的方法也会随之重新渲染,而computed中只有依赖的数据发生变化时,才会重新执行计算。
watch
<script>
const app = Vue.createApp({
data(){
return {
message: 'Hello World',
count: 4,
price: 7
}
},
watch: {
price(){
setTimeout(() => {
console.log('price change')
}, 3000)
}
},
template: `<div>{{message}}</div>`
});
const vm = app.mount('#root');
</script>
在watch中可以通过监听data函数中定义的数据,当数据发生变化时,可以执行一些异步操作。
- 在
watch中定义的监听方法中,有两个参数:当前值,上一个值
watch: {
price(current, prev){
console.log(current, prev)
}
},
在watch中也可以执行computed计算属性那样的操作,但是由于watch的特殊性,需要现在data中去定义值,然后才能在watch中进行侦听,最后在返回到页面上进行渲染,所有根据代码的简约性来看,不建议使用watch去做computed中能做的事。
总结
computed和methods都能实现的功能,建议使用computed,因为会有缓存。computed和watch都能实现的功能,建议使用computed,因为更加简洁。