computed和watch的全面分析

1.computed

1.1 定义

computed是计算属性,依赖于其他属性值进行计算,具有缓存性,当computed依赖的值发生改变时,computed才会再次进行计算。

1.2 使用

<template>
  <div>
    {{ fullName }}
  </div>
</template>
<script>
export default {
  name: 'Test',
  data() {
    return {
      firstName: 'Dell',
      lastName: 'Lee'
    }
  },
  computed: {
    fullName() {
      return this.firstName + ' ' + this.lastName
    }
  }
}
</script>

这里不可在data中重复声明fullName,否则会报如下图错误,因为在计算属性会定义并返回结果给变量fullName,变量不可重复定义和赋值。
在这里插入图片描述

1.3 get & set

get是根据计算属性获取当前computed返回的数据

set是监听computed返回的计算属性的变化

下面用一个实例来分析一下 get和 set的具体使用

<template>
  <div>
    姓:<input v-model="firstName"><br>
    名:<input v-model="lastName"><br>
    姓名一:<input v-model="fullName1"><br>
    姓名二:<input v-model="fullName2"><br>
  </div>
</template>

<script>
export default {
  name: 'Test',
  data() {
    return {
      firstName: 'Dell',
      lastName: 'Lee'
    }
  },
  computed: {
    fullName1() { // 返回当前computed计算属性的值
      return this.firstName + ' ' + this.lastName
    },
    fullName2: {
      get() { // get返回当前computed计算属性的值
        return this.firstName + ' ' + this.lastName
      },
      set(val) { // 监听当前computed计算属性值的变化,当属性值变化后,更新相关的源计算属性数据
        console.log(val) // fullName的值
        const names = val.split(' ')  // 将字符串分隔成字符串数组
        console.log(names)
        this.firstName = names[0]   // 当fullName变化时,将这个变化同步给firstName和lastName
        this.lastName = names[1]
      }
    }
  }
}
</script>

根据 姓 和 名 计算出姓名值 其中,姓名一的绑定是单向的, 姓名二的绑定是双向的。
在这里插入图片描述

1.当 姓 、名 改变时,姓名一、姓名二根据依赖的属性值进行计算 得到最终的姓名
在这里插入图片描述
2.当姓名一改变时, 姓、名 、姓名二都不会发生变化
在这里插入图片描述
3.当姓名二改变时,姓、名、姓名一 随着发生变化
在这里插入图片描述

改变fullName2, set()中获取到当前的值为 Dell2 Lee3 ,通过set中的操作,更改了依赖的源属性数据,当源属性数据改变时,fullName1也发生改变。
在这里插入图片描述

结合上边的代码进行分析,

1.computed 是计算属性,依赖firstName和lastName计算出姓名,当依赖的属性改变时,计算属性的返回值跟着变化。

2.姓名一 fullName1 的绑定是单向的,即 姓、名 改变,姓名一改变, 姓名一改变,姓、名 不改变。因为fullName1只设置了get

3.姓名二 fullName2 的绑定是双向的,即姓、名 改变,姓名二改变, 姓名二改变,姓、名 改变。因为fullName2设置了get和set

get获取当前computed所计算的属性值,set监听当前computed计算的属性值发生变化,变化后,将这种变化同步到依赖的属性值。

2.watch

2.1定义

watch为监听器,来响应数据的变化,当数据发生改变时,触发watch中的函数。

2.2使用

2.2.1简单数据类型

简单数据类型可直接监听

<template>
  <div>
    <input v-model="inputVal">
  </div>
</template>

<script>
export default {
  name: 'Test',
  data() {
    return {
      inputVal: ''
    }
  },
  watch: {
    inputVal() {
      console.log(this.inputVal)
    }
  }
}
</script>

2.2.2 复杂数据类型

当监听对象等复杂数据类型时,直接监听,不能起作用

<template>
  <div>
    <input v-model="listQuery.inputVal">
  </div>
</template>

<script>
export default {
  name: 'Test',
  data() {
    return {
      listQuery: { inputVal: '' }
    }
  },
  watch: {
    listQuery() {
      console.log(this.listQuery)
    }
  }
}
</script>

当输入框输入值的时候,并没有监听到相应的值的变化
在这里插入图片描述

启用深度监听

<template>
  <div>
    <input v-model="listQuery.inputVal">
  </div>
</template>

<script>
export default {
  name: 'Test',
  data() {
    return {
      listQuery: { inputVal: '' }
    }
  },
  watch: {
    listQuery: {
      handler(oldVal, newVal) {
        console.log(oldVal)
        console.log(newVal)
      },
      immediate:true,
      deep: true // 深度监听
    }
  }
}
</script>

可以发现,当启用深度监听后,可以监听到复杂数据类型的变化,但得到的值是一样的。之所以oldVal和newVal的值是一样的,原因在于它们的引用是同一个对象,watch不会保留数据的变化。
在这里插入图片描述

immediate属性

最初绑定的时候是不会执行的,要等到监听的值改变时才执行监听计算。那我们想要一开始就让他最初绑定的时候就执行需要设置immediate。
immediate:true

设置了immediate之后,刷新页面的时候控制台就输出了最初绑定的值。
在这里插入图片描述

deep属性

deep启用深度监听,不设置deep,无法监听到复杂数据类型的属性值变化。

简单数据监听和复杂数据监听

注意二者之间的写法是不同的

watch: {
    inputVal(oldVal, newVal) {
      console.log(oldVal, newVal)
    }
  }
watch: {
    listQuery: {
      handler(oldVal, newVal) {
        console.log(oldVal, newVal)
      },
      immediate: true,
      deep: true
    }
  }

handler 表示对象中属性变化的处理函数,这个函数只能叫这个名字,唯一不可变

解决方法一、 监听对象的某一属性

<template>
  <div>
    <input v-model="listQuery.inputVal">
  </div>
</template>

<script>
export default {
  name: 'Test',
  data() {
    return {
      listQuery: { inputVal: '' }
    }
  },
  watch: {
    'listQuery.inputVal': {
      handler(oldVal, newVal) {
        console.log(oldVal,newVal)
      }
    }
  }
}
</script>

在这里插入图片描述

解决方法二、 结合computed计算属性实现对象的监听

<template>
  <div>
    <input v-model="listQuery.inputVal">
  </div>
</template>

<script>
export default {
  name: 'Test',
  data() {
    return {
      listQuery: { inputVal: '' }
    }
  },
  computed: {
    input() {
      return this.listQuery.inputVal
    }
  },
  watch: {
    input(oldVal, newVal) {
      console.log(oldVal, newVal)
    }
  }

}
</script>

以上结合computed完成了对象的监听。

综上所述,简单总结一下:

computed 会依赖缓存中的计算属性值,当所依赖的属性值计算结果发生改变时才会再次触发而watch只要监听的数据重新渲染,不管值是否发生 发生变化都会触发,这样会导致性能上的降低。

二者都是用于监听数据,具体用法结合实际应用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值