Vue 响应式的本质

在 Vue 开发中,最容易出问题的地方往往是对 Vue 响应式系统的误解。

响应式的核心不在于"数据一变,页面就刷新",这是表象。真正的本质是数据和函数的关联

当数据与函数关联后,数据的变化会触发相应函数的重新运行。这里要明确两个关键点:哪些数据哪些函数关联了呢?

哪些数据会被关联?

1、函数中使用的数据:只有当函数用到了某个数据时,这个数据才与函数关联。例如,读取对象中的某个属性。

2、读取或使用的数据是响应式数据:只有 ref 或 reactive 包裹的数据才具备响应式特性,普通数据是不会触发关联函数运行的。

哪些函数会被监控?

被监控的函数,在 vue2 是放在 Wacther 内部的,在 vue3 是放在 effect 内部的。

1、render:渲染函数,也就解释了为什么数据一变,页面刷新,因为 render 是被监控的。

2、watchEffect:自动依赖追踪,数据变化时,函数会自动重新执行。

3、watch:显式地监听指定的数据变化,并执行相应回调。

4、computed:计算属性,它是基于响应式数据计算得来的,数据变化会重新计算值。

因此,只要满足这两点:响应式数据和被监控的函数,数据变化时,函数就会重新运行,页面表现才会随之更新。

举个 🌰 1

html 复制代码
<template>
  <div class="container">
    <p>count:{{ count }}</p>
    <p>double:{{ doubleCount }}</p>
    <button @click="count++" class="btn">increase</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
const doubleCount = ref(count.value * 2)
</script>

解释:

1、render 函数关联了 count 和 doubleCount 数据,count 是响应式数据,因此,count 变化,页面刷新。

2、为什么 doubleCount 没有变化?doubleCount 只是和 count 进行关联,但是响应式本质没有数据与数据的关联,是数据和函数的关联。因此 doubleCount 不会改变。

🌰 2

javascript 复制代码
import { ref, watchEffect } from 'vue'
const count = ref(0)
const doubleCount = ref(0)
watchEffect(() => {
  doubleCount.value = count.value * 2
})

解释:

1、现在被监控的函数有两个,render 和 watchEffect,在 watchEffect 中使用了 count,并且 count 是响应式数据,也就是说,render 函数关联两个数据,wacthEffect 关联一个数据。

2、当点击按钮改变 count 时,两个函数都会运行,wacthEffect 运行时,doubleCount 重新赋值,重新展示。

🌰 3

javascript 复制代码
import { ref, watchEffect } from 'vue'
const count = ref(0)
const useDouble = (count) => {
  const doubleCount = ref(count)
  watchEffect(() => {
    doubleCount.value = count * 2
  })
  return doubleCount
}
const doubleCount = useDouble(count.value)

解释:

1、为什么 doubleCount 没有变化?因为 useDouble 函数并没有被监控,只是一个普通的函数。

2、在 useDouble 函数中,有被监控的 wacthEffect 函数,但是函数内部没有读取某个属性,读取的 count 不是响应式数据,而是一个原始数据。

因此,count 变化后,render 运行,但是 watchEffect 不会执行。

🌰 4

javascript 复制代码
import { computed, ref } from 'vue'
const count = ref(0)
const doubleCount = computed(() => count.value * 2)

解释:

computed 被监控的函数关联了响应式数据 count,因此 count 变化后,render 函数和 computed 函数都会重新运行。

🌰 5

javascript 复制代码
import { computed, ref } from 'vue'
const count = ref(0)
const useDouble = (count) => {
  const doubleCount = computed(() => count * 2)
  return doubleCount
}
const doubleCount = useDouble(count.value)

解释:

useDouble 是普通函数,没有被监控,内部被监控的 computed 没有关联响应式数据,也没有读取某个对象的某个属性。因此 count 变化时,computed 函数不会重新运行。

🌰 6

javascript 复制代码
import { computed, ref } from 'vue'
const count = ref(0)
const useDouble = (count) => {
  const doubleCount = computed(() => count.value * 2)
  return doubleCount
}
const doubleCount = useDouble(count)

解释:

为什么这种写法可以改变 doubleCount 呢?因为 computed 函数读取了对象的属性,也就是我们传递的是响应式对象,而不是一个普通数据。实现了数据和函数直接的关联。

以上就是 Vue 响应式原理的本质,当我们遇到某些疑惑不能解决时,不妨分析一下其根源。

相关推荐
码事漫谈8 分钟前
比尔·盖茨这次谈的不是模型,是账单
前端·后端
mayaairi17 分钟前
JS BOM完全指南(二):事件轮询、三大尺寸家族与浏览器对象详解
开发语言·javascript·ecmascript
星栈1 小时前
AI 生成页面全是紫粉渐变?我用 ui-ux-pro-max-skill 重构了整个产品页
前端·weui
avi91111 小时前
【】js不同颜色(Vue 框架)今时今日2026年学编程入门(10月1日)
前端·vue.js·vue·vue框架·前端入门·vue入门·html上传
Fluxart.ai2 小时前
商品多角度图怎么做?Flux Art 从白底图到规格图、包装图的 10 步教程
开发语言·前端·javascript
前端繁华如梦2 小时前
React + Three.js 造了一个"乙烯基娃娃"3D 角色编辑器:配方驱动、程序化生成、还能跳舞
前端
繁华若梦7592 小时前
全项目 Skills 适配:把「会写代码的 Agent」变成「会按你们规范干活的同事」
前端
江华森2 小时前
云原生从0到1:Kubernetes 工作负载实战——Deployment/Service/滚动更新/弹性伸缩
前端·后端
江华森2 小时前
《云原生从0到1:4台华为云ECS搭建Kubernetes 1.28集群实录(上)——环境与踩坑全记录》
前端·后端