zoukankan      html  css  js  c++  java
  • [vue] computed 和 method

    计算属性

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

    Method

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

    举一个栗子

    <template>
    ...
    <div>
      <p>计算属性: {{ getComputedTotal }}</p>
      <p>计算属性: {{ getComputedTotal }}</p>
      <p>方法: {{ getTotal() }}</p>
      <p>方法: {{ getTotal() }}</p>
    </div>
    ...
    </template>

    <script>
    ...
    data() {
      return {
          a1,
          b2,
          c3
      }  
    },
    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 {
          showTimefalse,
      }  
    },
    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的渲染原理。

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

  • 相关阅读:
    EL 自定义函数
    Linux 软件安装管理
    Linux 网络环境查看命令
    Linux 用户和用户组的命令
    Linux 用户和用户组进阶命令
    Linux 用户和用户组的基本命令
    将博客搬至CSDN
    U盘做系统启动盘(PE)时的文件格式选择 HDD ZIP FDD
    STM32 的几种输入输出模式
    define 中强制类型转换 && 浮点数后面带f
  • 原文地址:https://www.cnblogs.com/rencoo/p/13430642.html
Copyright © 2011-2022 走看看