第六章、CompositionAPI中的watch与watchEffect

一、watch 监听响应式式数据;可以监听多个;

语法:watch(source, callback, options)
### source 可以是下面这几种情况:
- 一个函数,返回一个值
- 一个 ref
- 一个响应式对象
- ...或是由以上类型的值组成的数组
### callback 数据源改变时的回调,可以检测新旧值得变化
### options: 配置项: immediate/deep/flush/onTrack/onTrigger
示例:
2.1 监听一个或多个ref;无坑
const foo = ref('foo');
const bar = ref(‘bar’)

//1、 监听一个ref
watch(foo, (newFoo,preFoo) =>{
  console.log('newFoo->',newFoo,'preFoo->',preFoo)
})
//2、 监听多个ref
watch([foo,bar], ([newFoo,newBar],[preFoo,preBar]) =>{
  console.log('newFoo->',newFoo,'preFoo->',preFoo)
  console.log('newBar->',newBar,'preBar->',preBar)
})
2.2 监听一个ref类型的响应式对象;有坑:需要开启deep;同时存在问题;新旧值相同;无法检测旧值
const nested = ref({
  foo:{
    bar: 1
  },
  baz: 2
})

// 注意:ref包裹引用类型,默认监听不到,需要开启deep; 但开启之后,新值和旧值一样,无法监听旧值
watch(nested, (newNested,preNested) =>{
  console.log('newNested->',newNested,'preNested->',preNested)
},{
  deep: true //需要手动开启
})
2.3 监听一个reactive对象,默认开启deep;但仍存在2.2上述问题;无法检测旧值
const foobar = reactive({
  foo: 1,
  bar:{
   baz:2
 }
watch(foobar, (foobar,preFoobar) =>{
  console.log('foobar->',foobar,'preFoobar->',preFoobar)
})

😇: 如果上面写成getter函数形式,需要手动开启deep;但仍存在2.2上述问题;无法检测旧值

watch(() => foobar, (foobar,preFoobar) =>{
  console.log('foobar->',foobar,'preFoobar->',preFoobar)
},{deep: true})
2.4、监听一个reactive对象的多个属性,以及嵌套属性;source必须是函数返回一个值,即getter函数;无坑
watch([() => foobar.foo,() => foobar.bar.baz], ([newFFoo,newFBaz],[preFFoo,preFBaz]) =>{
  console.log('newFFoo->',newFFoo,'preFFoo->',preFFoo)
  console.log('newFBaz->',newFBaz,'preFBaz->',preFBaz)
})
2.6 完整示例
<template>
  <div id="app">
    <h3>watch</h3>
    <p><strong>说明: watch 显式指定依赖源,依赖源更新时执行回调函数</strong></p>
    <h5>监听一个或者多个ref</h5>
    <div>
      foo:{{foo}} bar:{{bar}}
      <button @click="foo+='~';bar+='~'">修改</button>
    </div>
    <h5>监听一个ref类型的响应式对象</h5>
    {{nested}}
    <button @click="nested.baz++">修改nested</button>
    <h5>监听一个reactive的响应式对象</h5>
    {{foobar}}
    <button @click="foobar.foo++;foobar.bar.baz++">修改foobar</button>
  </div>
</template>


<script setup>
import { defineComponent, ref, watch, reactive } from "vue";
const foo = ref('foo')
const bar = ref('bar')
const nested = ref({
  foo:{
    bar: 1
  },
  baz: 2
})

const foobar = reactive({
  foo: 1,
  bar:{
    baz:2
  }
})
//1、 监听一个ref
watch(foo, (newFoo,preFoo) =>{
  console.log('newFoo->',newFoo,'preFoo->',preFoo)
})
//2、 监听多个ref
watch([foo,bar], ([newFoo,newBar],[preFoo,preBar]) =>{
  console.log('newFoo->',newFoo,'preFoo->',preFoo)
  console.log('newBar->',newBar,'preBar->',preBar)
})
//3、 注意:ref包裹引用类型,默认监听不到,需要开启deep; 但开启之后,新值和旧值一样,无法监听旧值
watch(nested, (newNested,preNested) =>{
  console.log('newNested->',newNested,'preNested->',preNested)
},{
  deep: true
})
//4、 监听一个reactive对象,默认开启deep;新旧值相同,无法监听旧值
watch(foobar, (foobar,preFoobar) =>{
  console.log('foobar->',foobar,'preFoobar->',preFoobar)
})
// 注意:如果写成getter函数,必须开启deep;但同样存在如上问题,无法监听旧值
watch(() => foobar, (foobar,preFoobar) =>{
  console.log('foobar->',foobar,'preFoobar->',preFoobar)
},{deep: true})
//5、监听一个reactive对象的多个属性,以及嵌套属性;source必须是函数返回一个值
watch([() => foobar.foo,() => foobar.bar.baz], ([newFFoo,newFBaz],[preFFoo,preFBaz]) =>{
  console.log('newFFoo->',newFFoo,'preFFoo->',preFFoo)
  console.log('newFBaz->',newFBaz,'preFBaz->',preFBaz)
})
</script>

<style scoped></style>

二、watchEffect :自动收集依赖;依赖源更新自动触发;始终是最新的值

<button @click="nested.baz++">修改nested</button>

const nested = ref({
  foo:{
    bar: 1
  },
  baz: 2
})

watchEffect(() =>{
  console.log('fooE->',foo)  √
  console.log('nestedE->',nested.value.baz) √
  console.log('foobarE->',foobar.foo,foobar.bar.baz)  √

  // console.log(nested)  nested可检测不到,检测不到外部变化; nested.baz变化;就直接访问变化的值;
})

三、watch 与watchEffect区别

watch 懒执行,显式指定依赖源,依赖源更新时执行回调函数
watchEffect,立即执行,依赖源更新自动触发,始终返回最新的值

相同点:具有相同的享有相同的刷新时机和调试选项;副作用清除和停止监听用法相同
watch(source, callback, {
  flush: 'post',
  onTrack(e) {
    debugger
  },
  onTrigger(e) {
    debugger
  }
})

### 停止侦听
const stop = watch(source, callback)

// 当已不再需要该侦听器时:
stop()
### 副作用清除
watch(id, async (newId, oldId, onCleanup) => {
  const { response, cancel } = doAsyncWork(newId)
  // 当 `id` 变化时,`cancel` 将被调用,
  // 取消之前的未完成的请求
  onCleanup(cancel)
  data.value = await response
})

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值