史上最详细 VUE2.0 全套 demo 讲解 基础3(计算属性)

二天基础1+基础2突然突破了1000的收藏率,这使我更觉得大家认可我这种分享模式,这也看的出来vue的热度,我在这段时间的分享中,我一直脑海里在转,如何用最好的demo,和更好的流程去写文章,我相信从基础1开始看,一定能在工作上面有很多大的收获,接下来还是按着我们约定的来

1.本文分享 计算属性

2.代码运行vue-cli 2.1版本

3.组件代码都在components文件夹里

4.主代码逻辑都在 App.vue文件夹里

我什么都不要我只要

计算属性

在计算属性中,在我们前面基础1和基础2分享中有两个地方可以计算属性,我们认为所有属性的计算都是变向的在过滤值,通过数据的不断变化计算出不同的值和操作不同的方法
1.模板内的表达式
2.属性v-bind:里的可以进行表达式
3.指令中我们也可以进行表达式
以上三者优势在那里,简洁,省代码量,如果只是一个小操作,比方说一些简单的数值++,字符拼接,三元表达式,那使用相当好
以上三者的劣势,一但要处理的逻辑复杂,如果用到if()流程控制语句,变量赋值,代码量大了就很难于维护,我们可能就会想到用filter,那filter的场景适用于那里后面再说,先看一下简单的demo

App.vue

<template>
   <div>
        <p @click="count++">{{count+'分'}}</p>
        <input v-model='message'>
        <p>{{message.split('').reverse().join('') }}</p>
   </div>
</template>
<script>
    export default {
        data () {
            return {
                count : 0,
                message : ''
            }
        }
    }
</script>

从上面不难看出
1.模板内使用字符拼接,ok代码很清楚目的的所在
2.通过指令点击,也能少一个methods方法,也很简洁
3.通过输入框输入文字,在p标签里面进行计算转换的时候,那我觉得语意化就不是很强烈了,那用什么办法呢,用filter

用filter的优势
filter给我们用于计算和过滤一些模板表达式和v-bind:属性表达式一些弊端的地方进行计算,他会返回当前计算的值,可以进行传参在多地方共用这个过滤方法,
劣势
如果我们要计算多个数据不同变化结合而成的地方那filter就能难过到了,本质上filter我认为就是1v1,对单个数据进行过滤,可以进行传参,同方法,但不同参,非常适用

<template>
   <div>
        <input v-model='message'>
        <p>{{message | reverseString}}</p>
   </div>
</template>
<script>
    export default {
        data () {
            return {
                message : ''
            }
        },
        filters : {
            reverseString (value) {
                if(!value) return ''
                value = value.split('').reverse().join('') 
                return value
            }
        }
    }
</script>

我们把上个例子中第二个例子反转字符串这个方法用filter来实现,很明显示代码量多了那么一点点,但是整体的语意化相当明显了,让人一看这里就要进行一些过滤计算,能过reverseString,就能知道是反转字符串

1. computed

以上说了这么多前面的用法,因为我们模板语法和filter过滤来对computed的应用场景做一个铺垫,划分更加明确
computed可以做那些呢,适用于什么场景呢?
他规避了模板语法和filter两个所有的劣势,他的优势在于通过计算所有依赖的数据进行计算,然后返回一个值,记住可以依赖方法里所有的数据,只要一个数据发生变化,则会从新计算,来更新视图的改变,verygood,好东西看看怎么玩

应用场景 :
这是一个简单实用的应用场景,后面再做一个好玩的应用场景
我们填写备注的时候我们会有一个字数的限制和字数显示的限制,通过输入字符,我们要提醒用户还有输入多少字

<template>
   <div>
        <textarea v-model="content" :maxlength="totalcount"></textarea>
        <p>你还可以输入{{reduceCount}}字</p>
   </div>
</template>
<script>
    export default {
        data () {
            return {
                totalcount : 200 , //总共只给输入200字
                content : ''
            }
        },
        computed : {
            reduceCount () {
                return this.totalcount - this.content.length
            }
        }
    }
</script>

通过一直监听文字的字符的长度来出发compunted里reduceCount这个方法,来再次进行计算,返回值给视图,让视图进行变化。这也是一个很简单的demo例子,那很好,前面我说了可以监听多个数据,只要一个数据变了,整个方法就会从新计算,反馈到视图,这个方法只是一个简单的应用,请看下个demo例子,你们就能看懂一切的一切

这个例子是我想了一个多小时才次决定的例子,那就最就萨德事件使中韩足球最热门的一个事件,做IT做DEMO就是要玩起来,政治我们先不讨论,我们用技术来感化一下我们的爱国情
demo场景分析
1.我们要声明那些数据
一.比赛时间 用time来维护
二.比赛双方的进球数 用对象来维护
三.比赛的播报情况 在90分钟内,要显示中国领先或者韩国队领先或者双方僵持,如果到了90分种我们要显示中国队赢还是韩国队赢,还是平局
第三个数据非常关键,我们用什么来维护,可以说比赛情况是多样化的,用一个数据去定死维护,不符合场景,那我先列出那通过改变这些变化,我们不但要检测双方的进球数,还要通过时间来比对,是90分钟内,还是已经结束比赛了,来显示不同的文案。所以我们要不断监听两个维护的数据,一是比赛时间,二是比赛两队进球数

<template>
   <div>
        <h1>比赛时间{{time}}s</h1>
        <h2>直播播报{{result}}</h2>
        <div>
             <p>中国队进球数:{{team.china}}</p>
             <button @click="team.china++">点击中国队进一球</button>
             <p>韩国队进球数:{{team.korea}}</p>
             <button @click="team.korea++">点击韩国队进一球</button>
        </div>
   </div>
</template>
<script>
    export default {
        created () {
            let time =  setInterval(()=>{
                this.time++
                if(this.time == 90){
                    clearInterval(time)
                }
            },1000)
        },
        data () {
            return {
                time : 0,
                team : {
                    china : 0,
                    korea : 0
                }
            }
        },
        computed : {
            result () {
               if(this.time<90){
                   if(this.team.china>this.team.korea){
                       return '中国队领先'
                   }else if(this.team.china<this.team.korea){
                       return '韩国队领先'
                   }else{
                       return '双方僵持'
                   }
               }else{
                   if(this.team.china>this.team.korea){
                       return '中国队赢'
                   }else if(this.team.china<this.team.korea){
                       return '韩国队赢'
                   }else{
                       return '平局'
                   }
               }
            }
        }
    }
</script>

上面的我用点击事件来进行双方进球数,把上面这个demo运行一下我们可以充分的理解computed的涵意,说到底是观察一个或者多个数据,每当其中一个数据改变的时候,这个函数就会从新计算,还有就是通过观察所有数据来维护一个状态,就是所谓的返回一个状态值,从上面这个demo我们就可以很容易的知道computed到底用在什么场景,如何去维护返回一个多状态的场景

2.methods vs computed

在methods和computed可以做同样的事,但是,computed可以进行缓存,什么意思呢,就是在上个例子我们对比赛时间和两个球队的进球数进行了检测数据,如果随着时间的改变,但是球数没动,对于computed来说只会从新计算这个球数会进入缓存,不会再次计算,而从新计算的是这个时间,而且页面的dom更新也会出发methods来从新计算属性,所以如果不想让计算属性进入缓存,请求methods,但是我推荐用computed,语议化好一点麻,什么选项里就应该改做什么事,methods里面就是应该来管事件的。个人认为,同样的操作我就不演示demo了,看看官方的用法理解一下就可以了

3.computed vs watch

computed和watch都可以做同一件事,就像跑步运动员都可以跑步,但是分100米和1000米,术业有专功麻,两个选项都是对数据进行时时监听,但是两个的适用场景就不一样了

一.computed前面说了是适用于对多数据变动进行监听,然后来维护一个状态,就是返回一个状态

二.watch是对一个数据监听,在数据变化时,会返回两个值 ,一个是value(当前值),二个是oldvalue是变化前的值,我们可以通过这些变化也可以去维护一个状态,但是不符合场景,主要用于什么地方呢?主要用于监听一个数据来进行复杂的逻辑操作

  <template>
   <div>
        <h1>比赛时间{{time}}s</h1>
        <h2>直播播报{{result}}</h2>
        <div>
             <p>中国队进球数:{{team.china}}</p>
             <button @click="team.china++">点击中国队进一球</button>
             <p>韩国队进球数:{{team.korea}}</p>
             <button @click="team.korea++">点击韩国队进一球</button>
        </div>
   </div>
</template>
<script>
    export default {
        created () {
            let time =  setInterval(()=>{
                this.time++
                if(this.time == 90){
                    clearInterval(time)
                }
            },1000)
        },
        data () {
            return {
                time : 0,
                team : {
                    china : 0,
                    korea : 0
                },
                result : "双方僵持"
            }
        },
        watch : {
            time (value,oldval) {
               if(value<90){
                   if(this.team.china>this.team.korea){
                       this.result =  '中国队领先'
                   }else if(this.team.china<this.team.korea){
                       this.result =  '韩国队领先'
                   }else{
                       this.result =  '双方僵持'
                   }
               }else{
                   if(this.team.china>this.team.korea){
                       this.result =  '中国队赢'
                   }else if(this.team.china<this.team.korea){
                       this.result =  '韩国队赢'
                   }else{
                       this.result =  '平局'
                   }
               }
            },
            team (value,oldval){
                if(this.time<90){
                   if(value.china>value.korea){
                       this.result =  '中国队领先'
                   }else if(value.china<value.korea){
                       this.result =  '韩国队领先'
                   }else{
                       this.result =  '双方僵持'
                   }
               }else{
                   if(value.china>value.korea){
                       this.result =  '中国队赢'
                   }else if(value.china<value.korea){
                       this.result =  '韩国队赢'
                   }else{
                       this.result =  '平局'
                   }
               }
            }
        }
    }
</script>

以上代码和computed的产生的效果一模一样,但是很明显,就像我对computedwatch阐述过了应用场景,这个场景只是维护了一个比赛的状态,而不牵扯到逻辑操作,虽然也能完成,很明显,无论从代码量的比对,还是可读性,还是可维护性的比对都不胜于computed,但是说到底谁更强大呢,我还是老实的说watch更强大,虽然他有场景的局限性,但是他可以做牵扯到计算属性的一切操作,缺点watch只能一个一个监听

watch应用场景
我想信图片预加载大家肯定都有接触过,当图片量大的时候,为了保证页面图片都加载出来的时候,我们才把主页面给显示出来,再进行一些ajax请求,或者逻辑操作
那此时你用computed对这种监听一个数据然后进行一系列逻辑操作和ajax请求,那watch再适合不过了,如果用computed的话那你连实现都实现不了,只有用watch监听

  <template>
   <div v-show=show>
       <img src="https://img.alicdn.com/simba/img/TB14sYVQXXXXXc1XXXXSutbFXXX.jpg" alt="">
       <img src="//img.alicdn.com/tfs/TB1iZ6EQXXXXXcsXFXXXXXXXXXX-520-280.jpg_q90_.webp" alt="">
       <img src="https://img.alicdn.com/simba/img/TB1C0dOPXXXXXarapXXSutbFXXX.jpg" alt="">
       <img src="//img.alicdn.com/tfs/TB1iZ6EQXXXXXcsXFXXXXXXXXXX-520-280.jpg_q90_.webp" alt="">
   </div>
</template>
<script>
    export default {
        mounted () {
            var _this = this
            let imgs = document.querySelectorAll('img')
            console.log(imgs)
            Array.from(imgs).forEach((item)=>{
                let img = new Image()
                img.onload = ()=>{
                    this.count++
                }
                img.src=item.getAttribute('src')
            })
        },
        data () {
            return {
                count : 0,
                show : false
            }
        },
        watch : {
            count (val,oldval) {
                if(val == 4){
                    this.show = true
                    alert("加载完毕")
                    //然后可以对后台发送一些ajax操作
                }
            }
        }
    }
</script>

我们可以发现发四张图片都加载完毕的时候页面才显示出来

根据完方有一句话说的很重要的一句

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的 watcher 。这是为什么 Vue 提供一个更通用的方法通过 watch 选项,来响应数据的变化。当你想要在数据变化响应时,执行异步操作或开销较大的操作,这是很有用的。

基于这个官方的理解再总结我个人的整体理解。给出computed和watch的总结,记住这几点的总结,在做项目的时候想想这些总结,选择你的应用方法

computed :

监听多个数据或者一个数据来维护返回一个状态值 ,只要其中一个或多个数据发生了变化,则会从新计算整个函数体,从新返回状态值

watch :
只有一个一个监听据,只要这个数据发生变化,就会在返回两个参数,第一个是当前的值,第二个是变化前的值,每当变化的时候,则会触发函数体的里的逻辑行为,来进逻辑后续操作

其实我觉得计算属性也好,computed,watch这几个都不是有多难,如果浅层面上看很容易理解,如果从深层面上看,很多小伙伴会存在什么问题,就是会滥用,混用,这些计算属性,我想通过这些demo例子讲解和分析,我相信你又上一层楼了,ok终于可以完结这篇了,下一篇我想看看大家想学什么可以给我留言,如果那个多我就先讲那个
1.事件处理
2.表单控件
3.条件渲染
4.class 和 style 绑定

原文链接:https://juejin.im/post/58d8806bac502e0058d778a1

发表评论

登录后才能评论