基础/响应式基础-ref篇

98 阅读3分钟

文档一开始标题就是 声明响应式状态

什么是响应式状态?

能够被Vue检测到值的变化的变量就是响应式状态

最简单的响应式状态就是我们在编写Vue组件时,通过 ref 或者 reactive 声明的变量,例如:

import { ref, reactive } from 'vue'

const count = ref(0)
const form = reactive({})

Vue检测到这些响应式状态发生改变,会自动的更新DOM

什么时候需要声明响应式状态?

用户需要在页面上看到这个数据每次改变后的最新状态,那么这个数据应该是响应式的。

有时候父组件中的某些数据,需要传递给子组件并且这个数据会发生改变,也应该是响应式的

再比如组件内需要用到 setTimeout 或者 setInterval 定时器,声明一个 timer 来接收返回值,这个 timer 大多数情况下都不需要是响应式。【记得在 onBeforeUnmount 生命周期清除定时器】

DOM 更新时机

当你修改了响应式数据的状态,比如 count.value + 1 ,DOM会被自动更新,但并不是同步更新的

<template>
  <button @click="change">改变响应式数据状态</button>
  当前的值为: {{ count }}
</template>

<script setup>
  // 使用 script setup 省略了手动暴露状态和方法的步骤
  import { ref, onUpdated } from 'vue'
  
  const count = ref(0)
  
  function change() {
    count.value++
  }
  
  onUpdated() {
    // onUpdated是一个Vue内置的函数,我们传递一个callback作为参数,每次组件更新完成都会调用这个 callback。onUpdated也被称为钩子函数、生命周期函数
    console.log('组件更新了', count.value)
  }
  
</script>

我们声明了一个响应式数据 count 并且每次点击按钮,count 会在现有值的基础上加一,并且页面上的count也随之改变,每次点击都会打印出 组件更新了 和更新后的 count 。现在我们来调整一下代码:

<template>
  <button @click="change">改变响应式数据状态</button>
  当前的值为: {{ count }}
</template>

<script setup>
  // 使用 script setup 省略了手动暴露状态和方法的步骤
  import { ref } from 'vue'
  
  const count = ref(0)
  
  function change() {
    count.value++
    count.value++
    count.value++
    count.value++
    count.value++
  }
  
  onUpdated() {
    // onUpdated是一个Vue内置的函数,我们传递一个callback作为参数,每次组件更新完成都会调用这个 callback。onUpdated也被称为钩子函数、生命周期函数
    console.log('组件更新了', count.value)
  }
</script>

每次点击按钮会执行五次 count 自增的操作,大家可以猜测一下点击完一次按钮之后,打印的内容是什么

虽然每次点击 count 都加五,但是控制台只会打印一次 组件更新了 和加五之后的值。

Vue 会在“next tick”更新周期中缓冲所有状态的修改,以确保不管你进行了多少次状态修改,每个组件都只会被更新一次

如何能够每次自增都进行一次组件更新?

使用 nextTick

<template>
  <button @click="change">改变响应式数据状态</button>
  当前的值为: {{ count }}
</template>

<script setup>
  // 使用 script setup 省略了手动暴露状态和方法的步骤
  import { ref, nextTick } from 'vue'
  
  const count = ref(0)

//  function change() {
//    count.value++
//    nextTick(() => {
//     count.value++
//     nextTick(() => {
//       count.value++
//        nextTick(() => {
//          count.value++
//        })
//      })
//    })
//  }

  // 避免多层回调嵌套形成回调地狱
  async function change() {
    count.value++
    await nextTick()
    
    count.value++
    await nextTick()
    
    count.value++
    await nextTick()
    
    count.value++
    await nextTick()
    
    count.value++
  }
  
  onUpdated() {
    // onUpdated是一个Vue内置的函数,我们传递一个callback作为参数,每次组件更新完成都会调用这个 callback。onUpdated也被称为钩子函数、生命周期函数
    console.log('组件更新了', count.value)
  }
</script>

这个时候再点击按钮,每次都会打印五个 组件更新了