技术贴

vue3.0 watch

2023-09-10  本文已影响0人  zhudying
watch
  1. 单个数据监听
<script setup>
  import { ref, watch } from 'vue';
  const question = ref('')
  watch(
    question,
    (newV, oldV) => {}
  )  
</script>
  1. 多个数据监听
<script setup>
  import { ref, watch } from 'vue';
  const a = ref(1);
  const b= ref(2);
  // getter 函数
  watch(
    () => a.value  + b.value,
    (sum) => {}
  )
  // 数组形式
  watch(
    [a,  b],
    ([newA,newB]) => {}
  )
</script>
  1. 监听对象的值
<script setup>
import { reactive, watch } from 'vue';
const obj = reactive({
  count: 1
})
watch(
  () => obj.count,
  (count) => { }
)
</script>
深层侦听器

直接给 watch() 传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发:

<script setup>
import { reactive, watch } from 'vue';
const obj = reactive({
  count: 1
})
watch(
  obj,
  (newValue, oldValue) => {
   // 注意:`newValue` 此处和 `oldValue` 是相等的
  // 因为它们是同一个对象!
  } 
)
</script>

而在监听 obj.count 时不会创建深层侦听器

<script setup>
import { reactive, watch } from 'vue';
const state= reactive({
  obj: {
    name: '12'
  }
})
watch(
  () => state.obj,
  (newValue, oldValue) => {
   // 注意:当 obj 整体替换时,才会触发,state.obj.name = '4' 不会触发;state.obj = {name: '4' } 触发
  } 
)
</script>
deep ,强制转成深层侦听器

深度侦听需要遍历被侦听对象中的所有嵌套的属性,当用于大型数据结构时,开销很大。因此请只在必要时才使用它,并且要留意性能。

<script setup>
import { reactive, watch } from 'vue';
const state= reactive({
  obj: {
    name: '12'
  }
})
watch(
  () => state.obj,
  (newValue, oldValue) => {
   // 注意:state.obj.name = '4'  会触发
  },
  { deep: true }
)
</script>

watch 默认是懒执行的:仅当数据源变化时,才会执行回调。但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调
我们可以通过传入 immediate: true 选项来强制侦听器的回调立即执行:

<script setup>
import { ref, watch } from 'vue';
  const question = ref('')
  watch(
    question,
    (newV, oldV) => {},
    { immediate: true  }
  )  
</script>
watchEffect()

自动跟踪回调的响应式依赖

watchEffect() 可能会比深度侦听器更有效,因为它将只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性。
watchEffect 仅会在其同步执行期间,才追踪依赖。在使用异步回调时,只有在第一个 await 正常工作前访问到的属性才会被追踪。

<script setup>
import { ref, watchEffect } from 'vue';
let a = ref(1)
let b = ref('')
const sum = (num: any) => {
    let res = ''
    if (num < 5) {
        res = '年龄小于5'
    }
    return res
}
watchEffect(
    () => {
        let t = sum(a.value)
        b.value = t
        // 立即执行,自动追踪 a 的变化
    }
)
</script>
flush 回调的触发时机

当你更改了响应式状态,它可能会同时触发 Vue 组件更新和侦听器回调。
默认情况下,用户创建的侦听器回调,都会在 Vue 组件更新之前被调用。这意味着你在侦听器回调中访问的 DOM 将是被 Vue 更新之前的状态。
如果想在侦听器回调中能访问被 Vue 更新之后的 DOM,你需要指明 flush: 'post' 选项

<script setup>
import { watch, watchPostEffect } from 'vue';
watch(source, callback, {
  flush: 'post'
})
// 或 
watchPostEffect(() => {
  /* 在 Vue 更新后执行 */
})
</script>
停止侦听器

同步: 在 setup() 或 <script setup> 中用同步语句创建的侦听器,会自动绑定到宿主组件实例上,并且会在宿主组件卸载时自动停止。因此,在大多数情况下,你无需关心怎么停止一个侦听器。

异步: 如果用异步回调创建一个侦听器,那么它不会绑定到当前组件上,你必须手动停止它

<script setup>
import { watchEffect } from 'vue'

// 它会自动停止
watchEffect(() => {})

// ...这个则不会!
setTimeout(() => {
  watchEffect(() => {})
}, 100)
</script>

要手动停止一个侦听器,请调用 watch 或 watchEffect 返回的函数:

const unwatch = watchEffect(() => {})

// ...当该侦听器不再需要时
unwatch()
上一篇 下一篇

猜你喜欢

热点阅读