watchEffect()

watchEffect() 监测副作用函数。立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数:

<template>
  <div>
    <p>count: {{count}}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref, watchEffect } from '@vue/composition-api'

export default {
  setup() {
    // 监视 ref 数据源
    const count = ref(0)
    // 监视依赖有变化,立刻执行
    watchEffect(() => {
      console.log('count.value: ', count.value)
    })
    const increment = () => {
      count.value++
    }
    return {
      count,
      increment
    }
  }
}
</script>

停止侦听。当 watchEffect 在组件的 setup() 函数或生命周期钩子被调用时, 侦听器会被链接到该组件的生命周期,并在组件卸载时自动停止。

在一些情况下(比如超时就无需继续监听变化),也可以显式调用返回值以停止侦听:

监视 reactive 数据源
3秒后,点击+1按钮不再打印

<template>
  <div>
    <p>count: {{state.count}}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { reactive, watchEffect } from '@vue/composition-api'

export default {
  setup() {
    // 监视 reactive 数据源
    const state = reactive({
      count: 0
    })
    const stop = watchEffect(() => {
      console.log('state.count: ', state.count)
    })
    setTimeout(() => {
      stop()
    }, 3000)
    const increment = () => {
      state.count++
    }
    return {
      state,
      increment
    }
  }
}
// 3秒后,点击+1按钮不再打印
</script>

清除副作用。有时候当观察的数据源变化后,我们可能需要对之前所执行的副作用进行清理。举例来说,一个异步操作在完成之前数据就产生了变化,我们可能要撤销还在等待的前一个操作。为了处理这种情况,watchEffect 的回调会接收到一个参数是用来注册清理操作的函数。调用这个函数可以注册一个清理函数。清理函数会在下属情况下被调用:

副作用即将重新执行时
侦听器被停止 (如果在 setup() 或 生命周期钩子函数中使用了 watchEffect, 则在卸载组件时)
我们之所以是通过传入一个函数去注册失效回调,而不是从回调返回它(如 React useEffect 中的方式),是因为返回值对于异步错误处理很重要。

const data = ref(null)
watchEffect(async (id) => {
  data.value = await fetchData(id)
})

async function 隐性地返回一个 Promise - 这样的情况下,我们是无法返回一个需要被立刻注册的清理函数的。除此之外,回调返回的 Promise 还会被 `Vue 用于内部的异步错误处理。

在实际应用中,在大于某个频率(请求 padding状态)操作时,可以先取消之前操作,节约资源:

<template>
  <div>
    <input type="text"
      v-model="keyword">
  </div>
</template>

<script>
import { ref, watchEffect } from '@vue/composition-api'

export default {
  setup() {
    const keyword = ref('')
    const asyncPrint = val => {
      return setTimeout(() => {
        console.log('user input: ', val)
      }, 1000)
    }

    watchEffect(
      onInvalidate => {
        const timer = asyncPrint(keyword.value)
        onInvalidate(() => clearTimeout(timer))
        console.log('keyword change: ', keyword.value)
      },
      {
        flush: 'post' // 默认'post',同步'sync','pre'组件更新之前
      }
    )

    return {
      keyword
    }
  }
}
// 实现对用户输入“防抖”效果
</script>
Logo

前往低代码交流专区

更多推荐