vue3 watch

最后都变了- 提交于 2020-02-27 20:15:03

watch

监听ref

let a = ref(0)
let b = ref(1)
watch(() => {
  console.log('watch a+b', a.value + b.value)
})

watch(a, () => {
  console.log('watch a', a.value + b.value)
})

setTimeout(
  () => {
    a.value++
  }, 1000
)
setTimeout(
  () => {
    b.value++
  }, 2000
)

默认是先执行一次,  不指定监听的数据源时, 只要关联数据变化, 就会执行, 指定监听源时, 只有指定的数据变化后才会执行

 

监听reactive

let a = reactive({count: 1})
let b = reactive({count: 2})

watch(() => {
  console.log('a+b', a.count + b.count)
})

watch(() => a.count, () => {
  console.log('a.count', a.count + b.count)
})
watch(() => a, () => {
  console.log('a', a.count + b.count)
})
setTimeout(() => {
  a.count++
}, 1000)
setTimeout(() => {
  b.count++
}, 2000)

依然会先执行, 但是执行数据源必须精确指定

 

监听数组

let a = reactive({count: 1})
let b = ref(0)
watch(() => {
  console.log('a+b', a.count, b.value)
})

watch(() => a.count, () => {
  console.log('a.count', a.count, b.value)
})
watch(() => a, () => {
  console.log('a', a.count, b.value)
})

watch(b, () => {
  console.log('b', a.count, b.value)
})

watch(
  [() => a.count, b],
  ([newCount, newValue], [oldCount, oldValue]) => {
    console.log('new', newCount, newValue)
    console.log('old', oldCount, oldValue)
  }
)

setTimeout(() => {
  a.count++
  console.log('a change')
}, 1000)
setTimeout(() => {
  b.value++
  console.log('b change')
}, 2000)

 

 

stop 停止监听

let a = ref(0)
let stop = watch(() => {
  console.log('a', a.value)
})

setTimeout(() => {
  a.value++
  console.log('change')
  stop()
  console.log('stop')
}, 1000)

setTimeout(() => {
  a.value++
}, 2000)

setTimeout(() => {
  a.count++
  console.log('a change')
}, 3000)

 

clean

执行时机: watch重复调用时触发

  let stop = watch(a, (newVal, oldVal, clean) => {
    console.log('a', a.value)
    clean(
      () => {
        console.log('clean')
      }
    )
  }, {
    // lazy: true
  })
  setTimeout(
    () => {
      a.value++
      console.log('a change')
    }, 1000
  )
  setTimeout(
    () => {
      a.value++
      console.log('a change2')
    }, 2000
  )

watch 执行了三次, 所以clean会执行两次

lazy

不在初始化时执行watch中的函数

  let stop = watch(a, (newVal, oldVal, clean) => {
    console.log('a', a.value)
    clean(
      () => {
        console.log('clean')
      }
    )
  }, {
    lazy: true
  })
  setTimeout(
    () => {
      a.value++
      console.log('a change')
    }, 1000
  )
  setTimeout(
    () => {
      a.value++
      console.log('a change2')
    }, 2000
  )

watch执行了两次, clean执行了一次

使用stop时watch只执行了一次

  let a = ref(0)
  // 使用 clean 必须指定监听源
  let stop = watch(a, (newVal, oldVal, clean) => {
    console.log('a', a.value)
    clean(
      () => {
        console.log('clean')
      }
    )
  }, {
    lazy: true
  })
  setTimeout(
    () => {
      a.value++
      console.log('a change')
      stop()
    }, 1000
  )
  setTimeout(
    () => {
      a.value++
      console.log('a change2')
    }, 2000
  )

watch执行了一次, 不会调用clean

 

使用stop时watch执行了多次

  let a = ref(0)
  // 使用 clean 必须指定监听源
  let stop = watch(a, (newVal, oldVal, clean) => {
    console.log('a', a.value)
    clean(
      () => {
        console.log('clean')
      }
    )
  }, {
    lazy: true
  })
  setTimeout(
    () => {
      a.value++
      console.log('a change')
    }, 1000
  )
  setTimeout(
    () => {
      a.value++
      console.log('a change2')
      stop()
    }, 2000
  )

watch执行了两次, 但是在第二次执行完调用stop时, 会调用clean

 

一个使用clean节流的例子

不使用clean, 在频繁输入的时候, 会有大量无用请求

使用clean, 只有在两次改变间隔大于一定时间后才会真正请求

使用一个定时器模拟发出请求

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

<script>
  import {ref, watch} from 'vue'
  function fetchData(s) {
    return setTimeout(
      () => {
        console.log('s', s)
      }, 100
    )
  }
  export default {
    name: "Watch",
    setup() {
      let s = ref('')
      watch(s, (newVal, oldVal, clean) => {
        let handler = fetchData(newVal)
        // 每次重复执行时, 清空定时器
        clean(() => clearTimeout(handler))
      })
      return {
        s
      }
    }
  }
</script>

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!