计算属性

计算属性只有在它的相关依赖发生改变时才会重新取值

Method

method每次渲染的时候都会被执行

举一个栗子

<template>
...
<div>
  <p>计算属性: {{ getComputedTotal }}</p>
  <p>计算属性: {{ getComputedTotal }}</p>
  <p>方法: {{ getTotal() }}</p>
  <p>方法: {{ getTotal() }}</p>
</div>
...
</template> <script>
...
data() {
  return {
      a: 1,
      b: 2,
      c: 3
  }  
},
computed:{
   getComputedTotal() {
       console.log('触发computed')
       return this.a + this.b + this.c
   } 
},
methods:{
   getTotal() {
       console.log('触发method')
       return this.a + this.b + this.c 
   }
}
...
</script>

运行结果:

触发computed

触发method

触发method

可见,尽管计算属性在页面上'调用'了两次,实际上函数只执行了第一次,而方法每次都会执行

计算属性的好处

可以减少函数的执行,这对于巨大运算量的函数是一个很好的选择

什么场景下不能使用计算属性

我们需要获取一个运算结果,但是该结果是由非响应式属性组成时,比如 Date.now()

在这种场景下,如果我们采用计算属性,那么由于不是响应式依赖,我们得到的都是初始的结果,这不是我们所期望的

再举一个栗子

<template>
...
<div>
    <p>计算属性时间: {{ getComputedTime }}</p>
    <p>计算属性时间: {{ getComputedTime }}</p>
    <p>计算属性时间: {{ getComputedTime }}</p>
    <p v-if="showTime">几秒后, 计算属性时间: {{ getComputedTime }}</p>
    <p>方法时间: {{ getTime() }}</p>
    <p>方法时间: {{ getTime() }}</p>
    <p>方法时间: {{ getTime() }}</p>
    <p v-if="showTime">几秒后, 方法时间: {{ getTime() }}</p>
</div>
...
</template> <script>
...
data() {
  return {
      showTime: false,
  }  
},
created () {
    setTimeout(() => {
      this.showTime = true
    }, 5000)
},
computed:{
    getComputedTime () {
      return Date.now();
    },
},
methods:{
    getTime () {
      return Date.now()
    },
}
...
</script>

观察界面初次渲染结果

计算属性时间一直不变,每处都是初始值
方法时间,每处都是重新计算的结果(如果看不出可能是相隔时间太短…没关系,我们可以用下面的方式来观察)

由于我们设置了一个定时器来控制界面新的显示内容,因此过大约5s后再观察界面渲染的结果,我们发现
计算属性时间仍旧未改变,还是原来的值
方法时间,不仅新显示的内容重新计算了结果,而且之前的方法时间也都进行了重新计算(这是由于定时器触发了组件的重渲染, 因此所有的方法时间又都重新计算了一遍)

关于组件的重渲染,可以看一下另外一个栗子,有助于更加深刻的理解

...
<p>方法时间: {{ getTime() }}</p>
<button @click="setFullName">setFullName</button>
... methods:{
    getTime () {
      console.log('触发method时间')
      return Date.now()
    },
    setFullName () {
      console.log('触发name改变')
      this.fullName = 'John Doe'
    }
}

点击setFullName按钮后,运行结果:

console: 触发name改变
console: 触发methond时间

很惊讶,获取时间的方法也被执行了(尽管我们触发的是改变名字的事件);按照正常思路,大家肯定觉得,方法改变了哪一块,就应该重新渲染对应的那一块视图,而不应该将未改变的那块进行重渲染(时间)

但是, 查了官网之后,发现vue2.x并不是这样处理的,它的处理方式如下

在vue2.x中只要组件使用的众多状态中有一个发生变化,那么整个组件就要重新渲染
在这里vue做了优化:如果组件只有一个节点发送了变化,直接重新渲染整个组件的所有节点,会造成很大的性能浪费,因此vue使用了vnode,并对其进行缓存,在发生变化时,将上一次缓存的vnode和当前新创建的vnode进行对比,只更新发生变化的节点

也就是说会触发重渲染和重新计算,但是更新只是局部的更新(patch),不知道这样大家能不能明白

vue2.x改成这种方式,主要是出于性能的考虑,如果将每个节点都绑定一个watcher确实能达到咋们预期的哪块改变就重新渲染哪块,但是这样的话,再编译阶段给每个节点绑定一个watcher是一种很大的浪费,尤其是在界面上有成千上万的节点时,因此vue2.x采用了较vue1.x更加粗粒度的监听方式,也就是组件级别,只要组件级别监听到数据改变,那么就重渲染整个组件,但是在重渲染组件时采用了虚拟dom来优化这个过程,将每次计算的结果进行缓存,然后对比前后的两次的计算结果,只对发生变化的节点进行更新

以上就是关于vue的计算属性和方法之间区别的分享,在写栗子的过程中我们还捎带研究了下vue2.x的渲染原理。

每一次的疑惑,都是我们接近真理的最好机会,希望我们能把握这样的机会,而不是白白地错过真理,共勉!

[vue] computed 和 method的更多相关文章

  1. Vue computed属性

    computed vs methods 我们可以使用Vue中的method计算出学科的总分,最终得到的总数结果是相同的. 在上例的基础上,我们把computed区块中的totalMarks函数整体移到 ...

  2. vue computed 原理

    vue computed 主要依靠数据依赖来更新,这里不展示computed源代码,只展示核心思想. computed: { a(){ return this.b ++ } } data:{ b: 1 ...

  3. Vue computed props pass params

    Vue computed props pass params vue 计算属性传参数 // 计算 spreaderAlias spreaderAlias () { console.log('this. ...

  4. vuex bug & vue computed setter

    vuex bug & vue computed setter https://vuejs.org/v2/guide/computed.html#Computed-Setter [Vue war ...

  5. Vue中computed与method的区别

    转载于:https://segmentfault.com/a/1190000014478664?utm_source=tag-newest 1.computed区别于method的两个核心 在官方文档 ...

  6. vue的computed和method的区别

    (1)computed是响应式的,methods并非响应式. (2)computed是带缓存的 (3)computed中的成员可以只定义一个函数作为只读属性,也可以定义get/set变成可读写属性,这 ...

  7. vue computed监听多个属性

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. vue computed实现原理

    在 Vue.prototype._init 方法中的 initState 中有一个对于computed 的判断,如果有则执行 initComputed 方法初始化 computed. function ...

  9. vue computed、methods、watch的区别

    1.computed(计算属性)computed是计算属性,事实上和和data对象里的数据属性是同一类的(使用上), 2.methods(方法)写在html中的时候需要带()支持传参,且需要有触发条件 ...

随机推荐

  1. jmeter设置HTTP代理,录制APP脚本

    1.打开jmeter,“工作台”右键——“添加”——“非测试元件”——“HTTP代理服务器” 2.设置端口号,手机需与这里的端口号一致 3.新建线程组,“测试计划”右键——“添加”——“Threads ...

  2. Centos 6.4最小化安装后的优化(1)

    一.更新yum官方源 Centos 6.4系统自带的更新源速度比较慢,相比各位都有所感受,国内的速度慢的让人受不了.为了让centos6.4系统使用速度更快的yum更新源,一般都会选择更换源,详细步骤 ...

  3. 机器学习03 /jieba详解

    机器学习03 /jieba详解 目录 机器学习03 /jieba详解 1.引言 2.分词 2.1.jieba.cut && jieba.cut_for_search 2.2.jieba ...

  4. 数据可视化之powerBI技巧(二十三)Power BI可视化技巧,使用DAX自定义时间轴

    ​按照自然日历来展现疫情数据时,是这样的效果, 由于各个国家的疫情爆发时间不一致,按自然日期坐标轴很难比较各个国家的蔓延速度. 如果各个国家都从蔓延日开始统计,展示之后每日的确诊人数,就是同样的时间轴 ...

  5. Redis之对象

    1.对象的类型与编码 Redis使用对象来表示数据库中的键和值,每次我们在Redis的数据库中新创建一个键值对,我们至少会创建两个对象,一个键对象,另一个值对象. 每个对象都由一个redisObjec ...

  6. NoSQL数据库-MongoDB 学习(一)

    基本介绍 MongoDB 是为了快速开发互联网 Web 应用而设计的数据库系统 MongoDB 的设计目标是极简.灵活.作为 Web 应用栈的一部分 MongoDB 的数据模型是面向文档的,所谓文档是 ...

  7. 数据治理工具调研之DataHub

    1.项目简介 Apache Atlas是Hadoop社区为解决Hadoop生态系统的元数据治理问题而产生的开源项目,它为Hadoop集群提供了包括数据分类.集中策略引擎.数据血缘.安全和生命周期管理在 ...

  8. Unable to find a constructor that takes a String param or a valueOf() or fromString() method

    Unable to find a constructor that takes a String param or a valueOf() or fromString() method 最近在做服务的 ...

  9. 借鉴一个比较标准的后端RESTful API

    我们制定的 API 规范,使用了微服务架构所以做了一些改进,我们更偏向使用 http code 标识,不然需要自己处理成功或失败的逻辑,在 200 内再包一层显得啰嗦:并且微服务系列都不支持,Feig ...

  10. R 基础绘图体系-基础篇

    1.高水平绘图函数 生成数据 #模拟100位同学学号及三科成绩 num = seq(12340001,12340100) # 形成学号 x1 = round(runif(100,min = 80,ma ...