计算属性和侦听器

一、计算属性

1.1 什么是计算属性

首先通过一个示例来介绍计算属性,需求是把一个字符串倒序显示,具体代码如示例1所示:

<template>
  <div class="hello">
   <h1>{{msg}}转为{{msg.split('').reverse().join('')}}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

浏览器显示效果图:

总结:通过浏览器显示效果图可知,在插值表达式中通过调用一系列的字符串方法,把“Welcome to Your Vue.js App”字符串进行了倒序显示。再看示例1的代码,如果插值表达式中的代码过长或者逻辑较为复杂,就会变得臃肿不堪甚至难以阅读和维护,所以在遇到复杂的逻辑时,官方不推荐使用插值表达式,而是使用计算属性把逻辑复杂的代码进行分离。

用计算属性改写示例1的代码,具体代码如下:

<template>
  <div class="hello">
   <h1>计算属性:{{reversedMsg}}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  computed:{
    reversedMsg:function(){
      return this.msg.split('').reverse().join('')
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

 浏览器效果图:

 通过浏览器中的显示可以看到,利用计算属性依然可以完成字符串的倒序显示,计算属性可以分离逻辑代码,使代码的易维护性增强。以后遇到这种逻辑较为复杂的代码,均可以使用计算属性进行分离。所有计算属性都以函数的形式写在vue实例的compted选项内,最终返回计算后的结果。

1.2 计算属性用法

       在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。除了上面示例中的简单用法外,计算属性还可以依赖多个Vue实例的数据,只要其中任何一个数据变化,计算属性就会重新执行,视图也会更新。下面通过购物车商品总价的示例来展示,具体代码如下:

<template>
  <div class="hello">
   <h1>总价:{{prices}}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      package1:[
        {
          name:"iphone8",
          price:5688,
          count:1
        },
        {
          name:"ipad",
          price:2888,
          count:1
        }
      ],
      package2:[
        {
          name:"apple",
          price:3,
          count:5
        },
        {
          name:"banana",
          price:6,
          count:3
        }
      ]
    }
  },
  computed:{
    prices:function(){
      var prices=0;
      for(var i=0;i<this.package1.length;i++){
        prices+=this.package1[i].price*this.package1[i].count;
      }
      for(var i=0;i<this.package2[i].length;i++){
        prices+=this.package2[i].price*this.package2[i].count;
      }
      return prices;
    }
  }
};

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

 1.3 props动态传值与计算属性computed的结合

当props作为需要被转变的原始值传入,这时使用计算属性就可以了。动态加样式改变盒子的宽度。

示例代码(父组件App.vue):

<template>
  <div id="app">
   <Child :width="200"></Child>
  </div>
</template>

<script>
import Child from './components/Child.vue'
export default {
  components: { Child },
  name: 'App'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

子组件代码(Child.vue):

<template>
  <div :style="style" class="page">
    组件内容
  </div>
</template>

<script>
export default {
    name:'Child',
    data(){
        return{

        }
    },
    props:['width'],
    computed:{
        style:function(){
            return{
                width:this.width+"px"
            }
        }
    }

}
</script>

<style>
.page{
    border:1px solid #000;
}
</style>

页面效果图:

因为在传递宽度的时候要带单位(px),但每次都要写太麻烦,而且数值的计算一般都不带单位,所以统一在组件内使用计算属性实现。

1.4 计算属性缓存

我们从前面这些案例可以看到,调用methods里面的方法也可以与计算属性起到同样的作用,比如这里把示例1的功能用methods改写。

methods改写后的示例代码:

<template>
  <div class="hello">
 <!-- 这里的reversedMsg是方法,必须要带括号 -->
   <h1>methods改写:{{reversedMsg()}}</h1>
   <h1>methods改写:{{reversedMsg()}}</h1>
   <h1>methods改写:{{reversedMsg()}}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  computed:{
    
  },
  methods:{
    reversedMsg(){
      console.log("reversedMsg函数被调用了!")
      return this.msg.split('').reverse().join('')
    }

  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

显示效果:

 

 通过上面的改写,没有使用计算属性,而是在method里面定义了一个方法实现相同的效果,甚至该方法还可以接收参数,使用起来更加灵活。那既然使用methods就可以实现,为什么还要计算属性呢?

原因是计算属性是基于它的依赖缓存的,一个计算属性所依赖的数据发生变化,它才会重新取值,所以msg只要不改变,计算属性就不会更新,只解析一次。但是methods不同,只要重新渲染,它就会被调用,函数就会被执行。

所以,究竟是使用计算属性还是methods取决于是否需要缓存,当遍历大数组和计算量很大时,应当使用计算属性,除非不希望得到缓存。

 二、侦听器

2.1 什么是侦听器

Vue提供了一种更通用的方式来观察和响应Vue实例上的数据变动,称为侦听器

下面通过实例代码来讲解侦听器的使用,具体代码如下:

<template>
  <div class="hello">
  <input type="text" v-model="firstName"/>
  <input type="text" v-model="lastName"/>
  <h1>{{fullName}}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      firstName:"Foo",
      lastName:"Bar",
      fullName:"Foo Bar"
    }
  },
  watch:{
    firstName:function(val){
      this.fullName=val+" "+this.lastName
    },
    lastName:function(val){
      this.fullName=this.firstName+" "+val
    }

  }
  
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

浏览器效果图:

 2.2  计算属性VS侦听器

上面示例中的代码是命令式且重复的,将它使用计算属性修改之后进行比较,代码如下所示:

<template>
  <div class="hello">
    <input type="text" v-model="firstName"/>
    <input type="text" v-model="lastName"/>
    <h1>{{fullName}}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      firstName:"Foo",
      lastName:"Bar",
    }
  },
  computed:{
    fullName:function(){
      return this.firstName+""+this.lastName
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

 使用计算属性改写后感觉代码更简洁了。那为什么还要使用侦听器呢?

现在有一个需求:文本输入框中中的firstName和lastName其中一个内容发生了改变,fullName过1s钟之后再更新这个变化。

1.使用watch侦听器改写代码

<template>
  <div class="hello">
    <input type="text" v-model="firstName"/>
    <input type="text" v-model="lastName"/>
    <h1>{{fullName}}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      firstName:"Foo",
      lastName:"Bar",
      fullName:"Foo Bar"
    }
  },
  // computed:{
  //   fullName:function(){
  //     return this.firstName+""+this.lastName
  //   }
  // }
  watch:{
    firstName(val){
      setTimeout(()=>{
        this.fullName=val+" "+this.lastName  
      },1000)
      
    },
    lastName(val){
      setTimeout(()=>{
        this.fullName=this.firstName+" "+val 
      },1000)
      
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

2.使用计算属性computed改写代码,发现运行不出来结果,无法实现定时功能(异步操作)。

computed和watch之间的区别:
      1.computed能完成的功能,watch都可以完成。
      2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
两个重要的小原则:
   1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
   2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wanglingli95

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值