5.1 watch概述

效果:监督数据的改动(和Vue2中的watch效果一致)

特色:Vue3中的watch只能监督以下四种数据:

  1. ref界说的数据。
  2. reactive界说的数据。
  3. 函数回来一个值(getter函数)。
  4. 一个包含上述内容的数组。

5.2 监听ref根本类型

1、Vue2

关于根本类型的监听,Vue2便是一个函数,里边有newValue和oldValue回来新值和旧值。

watch: {
  sum(newValue, oldValue) {
    ......
  }
}

2、Vue3

在Vue3里运用watch要先import引入,而且watch里边传入两个参数:榜首个是监督的特点名,第二个是回调函数。

import {watch} from 'vue'
watch(sum, (newValue, oldValue) => {
  ......
})

这儿举一个最简略的比如:点按钮,数字+1。数字属于根本类型,咱们对它进行监听:

<template>
  <div class="person">
    <h2>当前求和为:{{sum}}</h2>
    <button @click="changeSum">点我sum+1</button>
  </div>
</template>
<script lang="ts" setup name="Person">
  import {ref,watch} from 'vue'
  // 数据
  let sum = ref(0)
  // 办法
  function changeSum(){
    sum.value += 1
  }
  watch(sum,(newValue,oldValue)=>{
    console.log('sum改动了', newValue, oldValue)
  })
</script>

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

留意:watch的榜首个参数传的是变量名,而不是它的value值,千万不要写成变量名.value。虽然它是ref类型,真正的值是.value,但watch并非监听它的value值。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

5.3 监听ref目标类型

先回顾一下Vue2监听目标的语法,它是一个目标,里边经过handler办法来获取新值和旧值。

watch: {
  sum: {
    handler(newValue, oldValue) {
      ......
    }
  }
}

Vue3假如监听的是一个目标类型,这个比较有意思,它会呈现两种状况:榜首个监听的是整个目标的地址是否改动;第二个是监听目标里的特点是否产生改动。

5.3.1 监听目标地址

监听整个目标地址是否产生改动,这个是最简略的,直接把目标放进去watch监听就能够了。

鄙人面的比如里有3个按钮,”修正姓名”和”修正年纪”都是改动目标里的特点值,而”修正整个人”是改动整个目标。

<template>
  <div class="person">
    <h2>姓名:{{ person.name }}</h2>
    <h2>年纪:{{ person.age }}</h2>
    <button @click="changeName">修正姓名</button>
    <button @click="changeAge">修正年纪</button>
    <button @click="changePerson">修正整个人</button>
  </div>
</template>
<script lang="ts" setup name="Person">
  import {ref,watch} from 'vue'
  // 数据
  let person = ref({
    name:'张三',
    age:18
  })
  // 办法
  function changeName(){
    person.value.name += '~'
  }
  function changeAge(){
    person.value.age += 1
  }
  function changePerson(){
    person.value = {name:'李四',age:90}
  }
  watch(person,(newValue,oldValue)=>{
    console.log('person改动了',newValue,oldValue)
  })
</script>

咱们发现,直接把目标放进去watch进行监听,它是无法监听内部特点的改动的,它只能监听整个目标有没有被从头赋值,也便是它的地址有没有改动。

5.3.2 监听目标特点

在实践的开发中,咱们更多的是监听目标里的特点改动。此刻需求手动敞开深度监听,也便是设置deep: true。

咱们在这儿持续做Vue2与Vue3的语法对比:

1、Vue2

在Vue2中,需求深度监听,只需求在与handler平级的地方设置deep:true即可。

watch: {
  person: {
    handler(newValue, oldValue) {
      ......
    }
    deep: true
  }
}

2、Vue3

在Vue3中,它相同是设置deep:true,区别就在于它是在watch的第三个参数里设置,第三个参数是一个目标,用来设置watch的一些配置项,比方{deep: true}。

watch(person,(newValue,oldValue)=>{
  console.log('person改动了',newValue,oldValue)
}, {
  deep: true
})

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

咱们发现,设置了deep:true深度监听之后,不管是特点值产生改动,仍是整个目标产生改动,它相同能监听得到。

当然除了deep:true之外,还有immediate:true也是比较常用,这个是当即监听的意思,它是先履行监听的函数,因此在初始化数据的时分,它就会当即调用一次watch监听。它的效果跟Vue2是完全一致的,在这儿就不再举例详述。

留意:咱们在监听目标的时分,假如是整个目标产生改动,那么它是能够辨认新目标与旧目标的。但假如目标不变,只是内部的特点产生改动,那么它的newValue与oldValue是一致的。

5.3.3 示例代码

请翻开F12控制台观看打印输出信息。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

5.4 监听reactive目标类型

5.4.1 reactive与ref的监听对比

reactive只能界说目标类型,它不像ref那样能够界说根本和目标两种类型。reactive与ref在监听的时分,主要有以下两点区别:

1、reactive类型是不允许改动整个目标的,也便是说不能给它赋值一个新目标,因此它就不会呈现监听整个目标产生改动的状况

2、默认敞开深度监听

5.4.2 监听reactive

其实监听reactive跟ref是相同的,也是把目标传进去watch里进行监听,不过它比ref更加便利,直接就能够监听到里边的特点改动,不需求设置deep:true。准确来说是Vue3强行设置深度监听,哪怕你设置deep:false也是没用的。

<template>
  <div class="person">
    <h2>姓名:{{ person.name }}</h2>
    <h2>年纪:{{ person.age }}</h2>
    <button @click="changeName">修正姓名</button>
    <button @click="changeAge">修正年纪</button>
    <button @click="changePerson">修正整个人</button>
  </div>
</template>
<script lang="ts" setup name="Person">
  import {reactive,watch} from 'vue'
  // 数据
  let person = reactive({
    name:'张三',
    age:18
  })
  // 办法
  function changeName(){
    person.name += '~'
  }
  function changeAge(){
    person.age += 1
  }
  function changePerson(){
    Object.assign(person,{name:'李四',age:80})
  }
  watch(person,(newValue,oldValue)=>{
    console.log('person改动了',newValue,oldValue)
  })
</script>

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

留意:示例中修正整个人(整个目标),它实践上是运用了Object.assign()办法,这个办法实践上并没有改动目标地址,它只不过是批量改动目标的各个特点而已。

5.4.3 示例代码

请翻开F12控制台观看打印输出信息。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

5.5 监听目标特点

除了监听整个目标以外,还能够指定监听目标的某一个特点。而目标里的特点,又能够分成两种类型:一个是根本类型的特点,一个是目标类型的特点。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

上述比如中,前面两个按钮是修正目标里的根本类型,后边3个按钮是修正目标里的目标类型,咱们对此逐个剖析:

5.5.1 根本类型特点

1、Vue2

在Vue2中,监听目标里的根本类型特点,以目标.特点用一个函数回来最新值和旧值。

watch: {
  'person.name'(newValue, oldValue) {
    ......
  }
}

2、Vue3

在Vue3监听一个目标,是直接把目标放进去watch里监听即可。现在要监听目标里的特点,咱们的榜首反应就会把目标.特点放进去监听。

例如在比如中想监听目标的姓名,很简略就会写成watch(person.name, ()=>{}),如下所示:

<template>
  <div class="person">
    <h2>姓名:{{ person.name }}</h2>
    <h2>年纪:{{ person.age }}</h2>
    <h2>轿车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
    <button @click="changeName">修正姓名</button>
    <button @click="changeAge">修正年纪</button>
    <button @click="changeC1">修正榜首台车</button>
    <button @click="changeC2">修正第二台车</button>
    <button @click="changeCar">修正整个车</button>
  </div>
</template>
<script lang="ts" setup name="Person">
  import {reactive,watch} from 'vue'
  // 数据
  let person = reactive({
    name:'张三',
    age:18,
    car:{
      c1:'奔驰',
      c2:'宝马'
    }
  })
  // 办法
  function changeName(){
    person.name += '~'
  }
  ......
  watch(person.name, (newValue,oldValue) => {
    console.log('person.name改动了',newValue,oldValue)
  })
</script>

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

咱们发现,咱们直接以目标.特点的方法放进去监听,Vue3是不允许的,它会宣布警告:这是一个无效的监听源,它只允许以下四种类型:getter函数、ref类型、reactive类型、以上3种类型组合的数组。

明显这个person.name只不过是一个字符串,属于根本类型特点,并非以上四种类型之一。

那么getter函数又是什么呢,其实这个警告说得比较含糊,反而官方文档说得非常接地气:所谓getter函数,它便是回来一个值的函数。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

文档地址:cn.vuejs.org/api/reactiv…

已然了解了getter函数,那么咱们只需求运用箭头函数将目标特点包裹一下就能够了:

watch(() => person.name, (newValue,oldValue) => {
  console.log('person.name改动了',newValue,oldValue)
})

此刻它就只监听目标的name特点,其它特点都不会监听:

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

5.5.2 目标类型特点

1、Vue2

Vue2监听目标里的目标类型特点,其实跟监听一般目标是相同的,以目标.特点作为键,经过handler办法来获取新值和旧值。

watch: {
  'person.car': {
    handler(newValue, oldValue) {
      ......
    }
  }
}

2、Vue3

Vue3关于目标里的目标类型特点的监听,它有两种方法:一是直接监听,二是运用箭头函数包裹后再监听。

(1)直接监听特点目标

根本类型需求箭头函数包裹成getter函数才干监听,而目标类型不需求,它直接传入watch即可监听。

let person = reactive({
  name:'张三',
  age:18,
  car:{
    c1:'奔驰',
    c2:'宝马'
  }
})
function changeC1(){
  person.car.c1 = '奥迪'
}
function changeC2(){
  person.car.c2 = '群众'
}
function changeCar(){
  person.car = {c1:'雅迪',c2:'爱玛'}
}
watch(person.car,(newValue,oldValue)=>{
  console.log('person.car改动了',newValue,oldValue)
})

这儿能够看出一个问题,把特点目标直接传入watch监听,它能够监听到目标里每一个特点的改动,可是假如整个目标产生改动,也便是给它赋值一个新的目标,它是无法监听的。

(2)箭头函数包裹特点目标(引荐)

除了直接监听,还能够像根本类型那样先包裹一个箭头函数,再进行监听:

watch(() => person.car,(newValue,oldValue)=>{
  console.log('person.car改动了',newValue,oldValue)
})

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

包裹了箭头函数之后,它反而无法监听里边的特点改动,它只重视目标的地址是否产生改动。假如想既监听内部特点,也监听目标地址,只需求再加上深度监听特点即可,即设置deep:true。

watch(() => person.car,(newValue,oldValue)=>{
  console.log('person.car改动了',newValue,oldValue)
}, {deep: true})

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

5.5.3 示例代码

请翻开F12控制台观看打印输出信息。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

5.6 监听多个数据

Vue3它能够一起监听多个数据,不需求分隔写多个watch,能够写在一个watch里,将需求监听的特点放进数组里传入watch监听即可。

这儿仍是举上述的比如,这次监听的是姓名和轿车这两个特点,但不监听年纪特点:

let person = reactive({
  name:'张三',
  age:18,
  car:{
    c1:'奔驰',
    c2:'宝马'
  }
})
function changeC1(){
  person.car.c1 = '奥迪'
}
function changeC2(){
  person.car.c2 = '群众'
}
function changeCar(){
  person.car = {c1:'雅迪',c2:'爱玛'}
}
watch([()=>person.name,person.car],(newValue,oldValue)=>{
  console.log('person.car改动了',newValue,oldValue)
})

留意:由于你是一起监听多个特点,因此里边只要某一个特点产生了改动,它都会触发。你传入的是数组,因此它也会回来整个数组,里边便是各个特点的值。

请翻开F12控制台观看打印输出信息。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

5.7 免除watch监听

咱们一旦运用了watch,它就会永久监听,咱们相同有办法将这个监听免除去。

在watch调用的时分,实践上它是有回来值的,咱们能够运用变量接纳并打印观察一下:

const stopWatch = watch(sum,(newValue,oldValue)=>{
  ......
})
console.log(stopWatch)

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

咱们发现它其实是一个函数来的,假如咱们想停止监听,只需求履行它即可。

举一个比如,假定sum从0开始累加1,当大于10的时分撤销监听。

<template>
  <div class="person">
    <h2>当前求和为:{{sum}}</h2>
    <button @click="changeSum">点我sum+1</button>
  </div>
</template>
<script lang="ts" setup name="Person">
  import {ref,watch} from 'vue'
  // 数据
  let sum = ref(0)
  // 办法
  function changeSum(){
    sum.value += 1
  }
  const stopWatch = watch(sum,(newValue,oldValue)=>{
    console.log('sum改动了',newValue,oldValue)
    if(newValue >= 10){
      stopWatch()
    }
  })
</script>

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

请翻开F12控制台观看打印输出信息。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

5.8 watchEffect

5.8.1 watchEffect与watch的区别

1、都能监听响应式数据的改动,不同的是监听数据改动的方法不同

2、watch:要明确指出监听的数据,它是一个惰性监听,你不指定它就不监听

3、watchEffect:不必明确指出监听的数据(函数中用到哪些特点,那就监听哪些特点)。

5.8.2 watchEffect的运用

咱们相同用一个简略的比如做一个比较,假定有一个需求:当水温到达60度,或水位到达80cm时,给服务器发恳求。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

1、watch完成方法

watch有多种监听方法,能够对水温文水位分别监听,也能够一起监听。这儿咱们运用最方便的方法,运用数组一起监听俩特点:

watch([temp,height],(value)=>{
  // 从value中获取最新的水温(newTemp)、最新的水位(newHeight)
  let [newTemp,newHeight] = value
  // 逻辑
  if(newTemp >= 60 || newHeight >= 80){
    console.log('给服务器发恳求')
  }
})

在这个需求里,触及到的变量总共是两个,分别是水温文水位,因此watch需求监听这两个特点才干完成。假如需求很杂乱,触及的变量有10个,那么你也只能老老实实的给watch指定这10个变量的监听。

2、watchEffect完成方法

watchEffect它不需求你去指定具体监听的特点,你只需求重视事务逻辑,只要代码触及到的变量,它会帮你自动监听。

假如用watchEffect来完成上面的需求,将会省去一切监听的特点,变得更加简洁和灵活。

watchEffect(()=>{
  if(temp.value >= 60 || height.value >= 80){
    console.log('给服务器发恳求')
  }
})

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

3、watchEffect的瑕疵

假如在if条件里运用了或运算符||,它会依照条件顺序进行监听,一旦前面的条件契合,则后续的条件将不会监听。

持续用上面的比如:当水温到达60度,或水位到达80cm时,给服务器发恳求。咱们的代码写成if(temp.value >= 60 || height.value >= 80),依照咱们的理解,不管是temp仍是height变量,只要哪一个条件契合它都会触发。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect

但watchEffect的机制并非如此,它认为榜首个条件是temp是否大于60,假如契合,则height的值不管是多少它都不关心。它只有在榜首个条件不契合的状况下,它才会重视第二个条件。

因此大家在运用watchEffect写逻辑的时分,要小心运用||运算符,假如真实想在watchEffect完成if的或运算符,能够多写一个if来奇妙的绕开或运算符。

watchEffect(()=>{
  if (temp.value >= 60) {
    console.log('给服务器发恳求')
  }
  if (height.value >= 80 && temp.value < 60) {
    console.log('给服务器发恳求')
  }
})

上面的代码将if(temp.value >= 60 || height.value >= 80)拆分成两段,假如水温temp大于60就发恳求,假如水位超过80且水温不到60也发恳求(由于水温到60就不必考虑水位了)。这样也相同能完美完成咱们的需求。

5.8.3 watchEffect的留意事项

1、watchEffect是当即监听的,相当于watch配置了immediate为true相同

2、watchEffect不管是根本类型仍是目标类型,它都能够监听到

3、watchEffect的免除监听方法跟watch是相同的

5.8.4 示例代码

请翻开F12控制台观看打印输出信息。

Vue3+vite+Ts+pinia—第五章 watch与watchEffect