3. 计算属性(只要是对属性的操作都可以写在计算属性里)和watch

<div id="app">
    {{text}}
    <br>
    <!--将123,456,789变成789,456,123-->
    <!--这种写法太臃肿了,这里的表达式包含 3 个操作,并不是很清晰,所以在遇到复杂的逻辑时应该使用 计算属性-->
    {{text.split(',').reverse().join(',')}}
    <br>
    <!--使用计算属性后的代码-->
    {{reserve}}
</div>
<script>
  var app = new Vue({
    el: '#app',
    data: {
      text: '123,456,789'
    },
    computed: {
      reserve(){
        return this.text.split(',').reverse().join(',')
      }
    }
  })
</script>

所有的计算属性都以函数的形式写在 Vue 实例内的computed 选项内,最终返回计算后的结果。

3.1. 计算属性用法

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

  <div id="app">
    {{priceSum}} /*44400-------我是app2里面的内容*/
  </div>
  <script>
    //需求:计算购物车中所有商品的价格
    var app2 = new Vue({
      el: '#aaa',
      data: {
        msg: '我是app2里面的内容'
      }
    })
    var app = new Vue({
      el: '#app',
      data: {
        //当package1和package2里面的数据改变,计算属性里的总价格也会同步改变
        package1: [
          {name: 'iphone',price: 3000,count:2},
          {name: 'ipad',price: 4000,count:3}
        ],
        package2: [
          {name: 'clother',price: 600,count:4},
          {name: 'computer',price: 12000,count:2},
        ]
      },
      computed: {
        priceSum(){
          var price1=0;
          var price2 = 0;
          for(var i =0;i<this.package1.length;i++){
            price1 += this.package1[i].price* this.package1[i].count
          }
          for(var i =0;i<this.package2.length;i++){
            price2 += this.package2[i].price* this.package2[i].count
          }
          return price1 + price2 +'-------'+app2.msg//这里可以通过计算属性访问app2实例里的内容
          //说明了计算属性还可以依赖多个 Vue 实例的数据
        }
      }
    })
  </script>

3.1.1. getter和setter

每一个计算属性都包含-个 getter 和一个 setter,我们上面的两个示例都是计算属性的默认用法 ,只是利用了 getter 来读取。在你需要时,也可以提供一个 setter 函数 , 当手动修改计算属性的值就像修改一个普通数据那样时,就会触发 setter函数,执行一些自定义的操作

  <div id="app">
    {{showName}}
  </div>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        firstName: 'wang',
        lastName: 'lifa'
      },
      computed: {
        //如果直接computed里的属性后面的值是function,那么默认就是调用了computed的getter方法
        //showName:function(){
        //  return this.firstName + this.lastName
        //}
        //等价于
        showName: {
          get:function(){
            return this.firstName + this.lastName
          }
        }
      }
    })
  </script>

setter的使用(直接this.computed里的对象名=’你新的值’,也就是你给它赋值的时候直接会调用set方法)

showName: {
  get:function(){
    return this.firstName + ' ' + this.lastName
  },
  set:function(newName){//set方法调用:直接this.showName= 'Wei,linlin'
    //newName是你设置的数据,也就是'Wei,linlin'
    var newName = newName.split(',')
    this.firstName = newName[0]
    this.lastName = newName[1]
  }
}

上面的代码当在页面上写this.showName=’Wei,linlin’的时候,页面上的名字就会从wanglifa变成weilinlin了

3.3. 计算属性缓存

小实例:

<div id="app">
{{reserve}} <br>
计算属性: <br>
{{now}} <br>
<br>
通过methods拿到的时间戳(方法必须加括号): <br>
{{this.now1()}}
</div>
<script>
  var app = new Vue({
    el: '#app',
    data: {
      text: '123,456,789',
      msg:'222'
    },
    computed: {
      reserve: function(){
        return this.text.split(',').reverse().join(',')
      },
      now: function(){
        return Date.now()
      }
    },
    methods: {
      now1:function(){
        return Date.now()
      }
    }
  })
</script>

上面代码运行后页面显示如下:


但是当修改了text的值后,

通过methods方法获取的时间戳的值变了,而计算属性获取的一直没变。
因为上面页面中的{{reserve}}里有对text值的操作,也就是页面中挂载了text,所以当text的值发生改变,页面会重新渲染,而methods里的方法只要页面重新渲染,就会重新执行,所以上面的时间值更新了。

而msg属性页面中并没用到,所以即使它变了,页面也不会去渲染,故methods里的方法没有执行----->>总结:页面中的方法:如果是调用方法,只要页面重新渲染。方法就会重新执行,不需要渲染,则不需要重新执行。


上面代码因为计算属性里的时间戳没有依赖于任何属性,所以不管页面怎么渲染都不会发生变化,而最上面的{{reserve}}里的值,因为是依赖与text属性的,所以当text属性变化,它也会跟着变化----->>>总结:计算属性,不管渲染不渲染,只要计算属性依赖的数据未发生变化,就永远不变。

调用 methods 里的方法也可以与计算属性起到同样的作用。

结论: 没有使用计算属性,在 methods 里定义了一个方法实现了相同的效果,甚至该方法还可以接受参数,使用起来更灵活。既然使用 methods 就可以实现,那么为什么还需要计算属性呢?

原因就是:计算属性是基于它的依赖缓存的。 一个计算属性所依赖的数据发生变化时,它才会重新取值,所以text 只要不改变,计算属性也就不更新。

何时使用: -----------使用计算属性还是 methods 取决于你是否需要缓存,当遍历大数组和做大量计算时,应当使用 计算属性,除非你不希望得到缓存。

data和computed的区别
data函数只会在组件创建的时候运行一次,之后data里数据的改变只是在各个钩子里变化,而computed是只要依赖的数据变了,它就会运行,就会重新改变

watch

一个对象,键是需要观察的表达式,值是对应回调函数(函数里的形参第一个是新值,第二个是旧值)。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。也就是只要你监听的属性改变时,它就会调用它里面的方法

var vm = new Vue({
  data: {
    a: 1,
    b: 2,
    c: 3,
    d: 4,
    e: {
      f: {
        g: 5
      }
    }
  },
  watch: {
    //当a的值变化时,就会调用这个函数
    a: function (val, oldVal) {
      console.log('new: %s, old: %s', val, oldVal)
    },
    // 方法名
    b: 'someMethod',
    // 深度 watcher
    e: {
      //handler这个属性时自带的回调函数名
      handler: function (val, oldVal) { /* ... */ },
      //加上这句后,e这个对象里的任何一个属性值变化,都会执行这个函数
      deep: true
    },
    // 该回调将会在侦听开始之后被立即调用
    d: {
      handler: function (val, oldVal) { /* ... */ },
      immediate: true
    },
    // watch vm.e.f's value: {g: 5}
    'e.f': function (val, oldVal) { /* ... */ }
  }
})

watch对象里的属性会在实例化的时候通过$watch()来调用,也就是

watch:{
    a: function(val,oldVal){
        console.log(val)
    }
}
//上面的代码会在实例运行后自动调用,也就是调用this.$watch所以上面的代码就相当于变成了
this.$watch('a',function(val,oldVal){console.log(val)})
//这时候watch里面的键的函数就变成了这里的回调函数了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容