Vue3之计算属性与侦听器

计算属性-computed:仅会在其响应式依赖更新时才重新计算

1、模板中的表达式虽然方便,但模板中写太多逻辑,会让模板变得臃肿,难以维护。
2、computed具有缓存作用。

<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})
// 一个计算属性 ref
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})

function calculateBooksMessage() {
  return author.books.length > 0 ? 'Yes' : 'No'
}
</script>

<template>
  // 这么写当然也可以,但是如果页面中很多地方需要使用,模板就会很臃肿
  <span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
  <span>{{ publishedBooksMessage }}</span>
  // 这么写当然也可以,但是页面重新渲染的时候,方法会再次调用,而computed具有缓存作用则不会
  <span>{{ calculateBooksMessage() }}</span>
</template>

侦听器-watch&watchEffect:在每次响应式状态发生变化时触发回调函数

计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态

  • watch
<script setup>
import { ref, watch } from 'vue'
const question = ref('')
const obj = reactive({ count: 0 })
// 可以直接侦听一个 ref
watch(question, async (newval, oldval) => {
  // 可以执行一些异步操作或者dom更新
  const res = await fetch('https://yesno.wtf/api')
})

// 监听对象属性,注意第一个参数是一个方法,切记不可以直接watch obj.count,因为得到的是number,不具备响应式
watch(
  () => obj.count,
  (count) => {
    console.log(`count is: ${count}`)
  }
)
// 深度监听:对象的属性(含多层级)发生改变,由于需要遍历嵌套属性,数据结构太深开销会很大
watch(
  () => state.someObject,
  (newValue, oldValue) => {
    // 注意:`newValue` 此处和 `oldValue` 是相等的
    // *除非* state.someObject 被整个替换了
  },
  { deep: true }
)
// 即时回调的侦听器:watch是惰性的,仅当数据源变化时,才会执行回调。可以通过如下配置立即执行
watch(source, (newValue, oldValue) => {
  // 立即执行,且当 `source` 改变时再次执行
}, { immediate: true })
</script>
  • watchEffect
    我认为watchEffect可以看做成watch+immediate: true+computed触发机制的合写
// 这里不同的是,watchEffect第一个参数不需要写监听的源
// 这个例子回调会立即执行,相当于immediate: true
watchEffect(async () => {
  const response = await fetch(
    // 这里有点像computed:每当 todoId.value 变化时,回调会再次执行
    `https://jsonplaceholder.typicode.com/todos/${todoId.value}`
  )
})
  • watch vs watchEffect
    相同点:都能响应式地执行有副作用的回调
    不同点:watch只追踪明确侦听的数据源,比如说我监听obj,只能监听obj的属性变化,但是watchEffect里面既可以监听obj的属性变化,也可以监听其他对象的属性变化。简单说,watch追踪更加明确,而watchEffect则不太明确。
  • 回调的触发时机
    当你更改了响应式状态,它可能会同时触发 Vue 组件更新和侦听器回调。默认情况下,侦听器回调的触发在DOM更新之前,这意味着你在侦听器回调中访问的 DOM 将是被 Vue 更新之前的状态。如果想在侦听器回调中能访问被 Vue 更新之后的 DOM,可通过如下配置:
watch(source, callback, {
  flush: 'post'
})
watchEffect(callback, {
  flush: 'post'
})

// 后置刷新的 watchEffect() 有个更方便的别名 watchPostEffect()
import { watchPostEffect } from 'vue'
watchPostEffect(() => {
  /* 在 Vue 更新后执行 */
})
  • 停止侦听器
const unwatch = watchEffect(() => {})
// ...当该侦听器不再需要时
unwatch()
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容