Vue3 Composition API - 数据监听

本文深入探讨Vue3中watchEffect和watch的使用方法,通过实例对比ref和reactive的响应式数据处理,讲解如何实现数据变化的监听及计算属性的更新。

Vue3 提供了两种方式进行数据监听:watchEffect 和 watch
watchEffect 基于 Proxy 代理的响应式数据,主动监听响应式数据的变化
watch 完全等效于 2.x this.$watch,属于懒执行

基本用法
<template>
  <div>
    <h3>{{ title }}</h3>
    <!-- ref -->
    <p>支持人数:{{ supNum }}</p>
    <p>反对人数:{{ oppNum }}</p>
    <p>支持率:{{ ratio }}</p>
    <button @click="changeNum(0)">支持</button>
    <button @click="changeNum(1)">反对</button>
    <!-- reactive -->
    <p>支持人数:{{ stateSupNum }}</p>
    <p>反对人数:{{ stateOppNum }}</p>
    <p>支持率:{{ stateRatio }}</p>
    <button @click="changeStateNum(0)">支持</button>
    <button @click="changeStateNum(1)">反对</button>
  </div>
</template>

<script>
import {
  ref,
  reactive,
  toRefs,
  readonly,
  computed,
  watchEffect,
  watch,
} from 'vue'

export default {
  props: {
    title: String,
  },
  // 初始化 props 和 beforeCreate 之间
  setup(props) {
    // 构建响应式数据 ref - 一般处理简单值的响应式,基于 Object.defineProperty 监听 value 值
    let supNum = ref(0)
    let oppNum = ref(0)
    const changeNum = (type) => {
      type === 0 ? supNum.value++ : oppNum.value++
    }
    // 计算属性
    let ratio = computed(() => {
      let total = supNum.value + oppNum.value
      return total === 0
        ? '--'
        : ((supNum.value / total) * 100).toFixed(2) + '%'
    })

    // 构建响应式数据 reactive - 基于 Proxy 对数据进行深度监听,以此构建响应式
    let state = reactive({
      stateSupNum: 0,
      stateOppNum: 0,
    })
    const changeStateNum = (type) => {
      type === 0 ? state.stateSupNum++ : state.stateOppNum++
    }
    // 把 reactive 中的每一项变成 ref 响应式数据
    // console.log(toRefs(state))
    // 计算属性
    let stateRatio = computed(() => {
      let total = state.stateSupNum + state.stateOppNum
      return total === 0
        ? '--'
        : ((state.stateSupNum / total) * 100).toFixed(2) + '%'
    })

    // 只读数据
    let data = reactive({
      name: 'Brady',
      age: 34,
    })
    let dataReadonly = readonly(data)

    // 基于 Proxy 代理的响应式数据
    // watchEffect(() => {
    // console.log(props.title)
    // console.log(state.stateSupNum)
    // })

    // 监听 ref
    watch(supNum, (count, prevCount) => {
      // console.log(count, prevCount)
    })
    // 监听 多个 ref
    watch(
      [supNum, oppNum],
      ([supCount, oppCount], [supPrevCount, oppPrevCount]) => {
        console.log(supCount, supPrevCount)
        // console.log(oppCount, oppPrevCount)
      }
    )
    // 监听 reactive
    watch(state, (count, prevCount) => {
      // console.log(count, prevCount)
    })
    // 监听 reactive 中的单个属性
    watch(
      () => state.stateOppNum,
      (count, prevCount) => {
        // console.log(count, prevCount)
      }
    )

    return {
      supNum,
      oppNum,
      changeNum,
      ratio,
      ...toRefs(state),
      changeStateNum,
      stateRatio,
    }
  },
}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值