监听 ref 数据

780 阅读1分钟
监听一个 ref 数据

📝 监听 age 的变化,做一些操作。

<template>
  <p>{{ age }}</p>
  <button @click="age++">click</button>
</template>

<script>
  import { watch, ref } from 'vue'
  export default {
    name: 'App',
    setup() {
      const age = ref(18)
      // 监听 ref 数据 age,会触发后面的回调,不需要 .value
      watch(age, (newValue, oldValue) => {
        console.log(newValue, oldValue)
      })

      return { age }
    }
  }
</script>
监听多个 ref 数据

📝 可以通过数组的形式,同时监听 age 和 num 的变化。

<template>
  <p>age: {{ age }} num: {{ num }}</p>
  <button @click="handleClick">click</button>
</template>

<script>
  import { watch, ref } from 'vue'
  export default {
    name: 'App',
    setup() {
      const age = ref(18)
      const num = ref(0)

      const handleClick = () => {
        age.value++
        num.value++
      }
      // 数组里面是 ref 数据
      watch([age, num], (newValue, oldValue) => {
        console.log(newValue, oldValue)
      })

      return { age, num, handleClick }
    }
  }
</script>
立即触发监听
<template>
  <p>{{ age }}</p>
  <button @click="handleClick">click</button>
</template>

<script>
  import { watch, ref } from 'vue'
  export default {
    name: 'App',
    setup() {
      const age = ref(18)

      const handleClick = () => {
        age.value++
      }

      watch(
        age,
        (newValue, oldValue) => {
          console.log(newValue, oldValue) // 18 undefined
        },
        {
          immediate: true
        }
      )

      return { age, handleClick }
    }
  }
</script>
开启深度监听 ref 数据

解决 1:当然直接修改整个对象的话肯定是会被监听到的(注意模板中对 obj 的修改,相当于修改的是 obj.value)。

<template>
  <p>{{ obj.hobby.eat }}</p>
  <button @click="obj = { hobby: { eat: '面条' } }">修改 obj</button>
</template>

<script>
  import { watch, ref } from 'vue'
  export default {
    name: 'App',
    setup() {
      const obj = ref({
        hobby: {
          eat: '西瓜'
        }
      })
      watch(obj, (newValue, oldValue) => {
        console.log(newValue, oldValue)
        console.log(newValue === oldValue)
      })

      return { obj }
    }
  }
</script>

解决 2:开启深度监听 ref 数据。

watch(
  obj,
  (newValue, oldValue) => {
    console.log(newValue, oldValue)
    console.log(newValue === oldValue)
  },
  {
    deep: true
  }
)
  1. 解决 3:还可以通过监听 ref.value 来实现同样的效果。

🧐 因为 ref 内部如果包裹对象的话,其实还是借助 reactive 实现的,可以通过 isReactive 方法来证明。

<template>
  <p>{{ obj.hobby.eat }}</p>
  <button @click="obj.hobby.eat = '面条'">修改 obj</button>
</template>

<script>
  import { watch, ref } from 'vue'
  export default {
    name: 'App',
    setup() {
      const obj = ref({
        hobby: {
          eat: '西瓜'
        }
      })
      watch(obj.value, (newValue, oldValue) => {
        console.log(newValue, oldValue)
        console.log(newValue === oldValue)
      })

      return { obj }
    }
  }
</script>

监听普通数据

监听响应式对象中的某一个普通属性值,要通过函数返回的方式进行(如果返回的是对象/响应式对象,修改内部的数据需要开启深度监听)。

<template>
  <p>{{ obj.hobby.eat }}</p>
  <button @click="obj.hobby.eat = '面条'">修改 obj</button>
</template>

<script>
import { watch, reactive } from 'vue'
export default {
  name: 'App',
  setup() {
    const obj = reactive({
      hobby: {
        eat: '西瓜',
      },
    })
    // 把 obj.hobby 作为普通值去进行监听,只能监听到 obj.hobby 自身的变化
    /* watch(
      () => obj.hobby,
      (newValue, oldValue) => {
        console.log(newValue, oldValue)
        console.log(newValue === oldValue)
      }
    ) */
    // 如果开启了深度监听,则能监听到 obj.hobby 和内部数据的所有变化
    /* watch(
      () => obj.hobby,
      (newValue, oldValue) => {
        console.log(newValue, oldValue)
        console.log(newValue === oldValue)
      },
      {
        deep: true,
      }
    ) */
    // 能监听影响到 obj.hobby.eat 变化的操作,例如 obj.hobby = { eat: '面条' } 或 obj.hobby.eat = '面条',如果是 reactive 直接对 obj 的修改则不会被监听到(ref 可以)
    watch(
      () => obj.hobby.eat,
      (newValue, oldValue) => {
        console.log(newValue, oldValue)
        console.log(newValue === oldValue)
      }
    )
    return { obj }
  },
}
</script>