前言
在上一篇文章中,讲过了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
,因为更加简洁。