彻底理解Vue中的计算属性(computed)、方法(methods)和侦听器(watch)

彻底理解Vue中的计算属性(computed)、方法(methods)和侦听器(watch)

前言:在学习Vue这个框架的时候,我们都会接触到里面的计算属性,方法,侦听器,但是对于初学者来说,很容易把这些概念混淆,所以准备写一篇文章来彻底讲清楚这三个属性。

  1. 计算属性(computed)

对于初学者来说,可能还不清楚计算属性、方法、侦听器这些属性该写在哪里,我这里就简单写一个vue2的模板,当然代码不是千篇一律的,每个人的代码格式都可能不同,但是大概的规范是要遵循的,我这里只是列举的一个比较常见的写法。如果你是Vue大佬,那么请忽略这一点。

    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script type='text/javascript'>
        const options = {
        	//指定你这个Vue实例需要挂载到哪里,或者说哪个容器
            el:'#app',
            //数据
            data() {
                return {
                    count: 123
                }
            },
            //方法
            methods: {

            },
            //计算属性
            computed: {

            },
            //侦听器
            watch: {

            }
        }
        const vm = new Vue(options);
    </script>

在学习计算属性(computed)之前,我们先来理解理解计算属性这四个字,computed这个英文单词是计算的意思,那么我们可以思考下,计算什么呢?这里给出一个简单的例子来帮助大家理解

我们知道,可以在Vue的插值中写表达式比如这样:

<body>
    <div id='app'>{{books.length>0?'isOk':'notOk'}}</div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script type='text/javascript'>
        const options = {
            el:'#app',
            data() {
                return {
                    books: ['西游记','水浒传','三国演义','红楼梦']
                }
            },
            methods: {

            },
            computed: {

            },
            watch: {

            }
        }
        const vm = new Vue(options);
    </script>
</body>

此时页面上展示的效果肯定是isOk,为什么呢?因为books.length>0?‘isOk’:'notOk’计算出来的值就是isOk,在Vue的插值语法中,写的就是表达式。到这里我们可以想想看,books.length>0?‘isOk’:'notOk’这个表达式像不像是在计算某个值,这里就相当于是这个表达式计算出了isOk这个值,然后渲染到页面上去。我们可以这样理解计算这个词。
但是有一个问题,就是如果我们的页面上有很多地方都需要用到这个计算过程呢?难道我们每个地方都去写一遍这个吗,那不是多写了好多代码吗,而且我们并不知道这个表达式的复杂程度。就比如这样,我们可能在很多地方都用到这个计算出来的值,那么我们每个地方都去写这个表达式那就太麻烦了,当然你现在可能会觉得不麻烦,就这?写这点东西算个啥呀,感觉还好啊。其实不是这样的,因为在未来的前端开发中,你所接触到的代码量不可能只是我这一点,你会编写很多的代码,到时候就比较复杂了。

    <div id='app'>
        <div>{{books.length>0?'isOk':'notOk'}}</div>
        <p>{{books.length>0?'isOk':'notOk'}}</p>
        <a href="###">{{books.length>0?'isOk':'notOk'}}</a>
    </div>

此时,Vue就给了我们一个computed属性,我们就叫他计算属性,
可以理解成这个属性就是用来计算的。那我们怎么写呢?computed里面写什么呢?别急,我来给你演示下

<body>
    <div id='app'>
        <div>{{books.length>0?'isOk':'notOk'}}</div>

        <p>{{books.length>0?'isOk':'notOk'}}</p>

        <a href="###">{{books.length>0?'isOk':'notOk'}}</a>

        <div>{{myFirstComputed}}</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script type='text/javascript'>
        const options = {
            el:'#app',
            data() {
                return {
                    books: ['西游记','水浒传','三国演义','红楼梦']
                }
            },
            methods: {

            },
            computed: {
                myFirstComputed() {
                    return this.books.length>0?'isOk':'notOk'
                }
            },
            watch: {

            }
        }
        const vm = new Vue(options);
    </script>
</body>

像这样,直接将函数编写在computed里面就可以了,然后再{{}}中编写就好了。
这里解释一下,我们再computed里面编写的函数都会被挂载在Vue实例上面去,所以我们直接使用就可以了。我们在控制台打印一下vm,返回的数据中就有我们刚才写的函数
在这里插入图片描述
有了这个computed,我们就可以少些很多代码了,相当与我们把很多代码直接封装到一个地方,需要用的地方直接调这个属性名就可以了。

讲到这里,我需要大家都记住一句话,Vue官方文档里面的话“对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性。”后面会用到这句话。
2. ### 方法(methods)

依葫芦画瓢,方法和计算属性相同点,就是将函数写在methods中,需要用的地方直接调用就是了。

<body>
    <div id='app'>
        <div>{{books.length>0?'isOk':'notOk'}}</div>

        <p>{{books.length>0?'isOk':'notOk'}}</p>

        <a href="###">{{books.length>0?'isOk':'notOk'}}</a>

        <div>{{myFirstComputed}}</div>

        <div>{{myFirstMethod()}}</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script type='text/javascript'>
        const options = {
            el:'#app',
            data() {
                return {
                    books: ['西游记','水浒传','三国演义','红楼梦']
                }
            },
            methods: {
                myFirstMethod() {
                    return this.books.length>0?'isOk':'notOk'
                }
            },
            computed: {
                myFirstComputed() {
                    return this.books.length>0?'isOk':'notOk'
                }
            },
            watch: {

            }
        }
        const vm = new Vue(options);
        console.log(vm);
    </script>
</body>

打印vm,多了一个函数,这里和计算属性有点区别,大家都可以看出来,多添加的这个属性是一个函数,所以我们调用的时候就应该写成函数的形式。
在这里插入图片描述

综上所述,我们发现计算属性能实现的效果,我们用方法也能实现,也就是说,两种方式的最终结果确实是完全相同的。那他们的区别在哪里呢?

计算属性和方法的区别:让我们先来想想之前说的那句话,“对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性。”为什么对于任何包含响应式数据的复杂逻辑,都应该使用计算属性,原因时计算属性是基于它们的响应依赖关系缓存的,计算属性只在相关响应式依赖发生改变时它们才会重新求值。也就是说我们的数据books没有改变的话,就不会重新求值,会调用之前计算属性返回的结果。这里就有一个缓存,这个缓存就是之前计算属性返回的值。但是方法不是这样的,方法没有这个机制,方法是无论哪里调用了,就会执行这个函数。所以,计算属性的优点其实就是减少了资源的消耗。比如说你的计算属性里面一大堆逻辑需要处理,如果你用计算属性就可以不去每次执行(当然是响应式数据没有改变的情况下),但是如果你用方法,就无意间做了很多没必要的事,明明可以解决的内存资源,何必要浪费呢?

  1. 侦听器(watch)

侦听器其实就是侦听某个属性值,只要这个值发生变化就会调用这个侦听函数,侦听函数名就是这个属性名。

<body>
    <div id='app'>
        <div>{{books.length>0?'isOk':'notOk'}}</div>

        <p>{{books.length>0?'isOk':'notOk'}}</p>

        <a href="###">{{books.length>0?'isOk':'notOk'}}</a>

        <div>{{myFirstComputed}}</div>

        <div>{{myFirstMethod()}}</div>


        <input type="text" v-model="firstname">
        {{fullname}}


    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script type='text/javascript'>
        const options = {
            el:'#app',
            data() {
                return {
                    books: ['西游记','水浒传','三国演义','红楼梦'],
                    firstname:'李',
                    lastname:'四',
                    fullname:''
                }
            },
            methods: {
                myFirstMethod() {
                    return this.books.length>0?'isOk':'notOk'
                }
            },
            computed: {
                myFirstComputed() {
                    return this.books.length>0?'isOk':'notOk'
                }
            },
            watch: {
                firstname() {
                    this.fullname = this.firstname + this.lastname;
                }
            }
        }
        const vm = new Vue(options);
        console.log(vm);
    </script>

在这里的话,只要firstname改变,就会调用firstname这个监听器。

那么监听器和计算属性有什么区别呢?
四个字来总结:各有千秋

就上面侦听器那个例子,我们可以用计算属性来实现,直接写一个计算属性,return一个this.firstname + this.lastname就可以了。但是为什么要写个监听器呢,还得多添加一个属性值fullname。确实是这样的,这里就展现出了计算属性的优点。但是,如果我是想异步改变值呢?比如说我想在改变了firstname值之后五秒钟后才改变fullname,你计算属性怎么写?
改变firstname延时5秒改变fullname的值正确写法

watch: {
                firstname() {
                    setTimeout(()=>{
                        this.fullname = this.firstname + this.lastname;
                    },5000)
                }
            }

计算属性怎么写呢?

 computed: {
                myFirstComputed() {
                    setTimeout(()=>{
                        return this.books.length>0?'isOk':'notOk'
                    },5000);
                }
            },

这样?这是不可以的。
所以,侦听器和计算属性各有千秋。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值