当前位置: 首页 > article >正文

Vue 响应式的本质

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

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

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

哪些数据会被关联?

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

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

哪些函数会被监控?

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

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

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

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

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

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

举个 🌰 1

<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

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

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

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

解释:

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

🌰 5

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

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 响应式原理的本质,当我们遇到某些疑惑不能解决时,不妨分析一下其根源。


http://www.kler.cn/news/341864.html

相关文章:

  • 12.5 Linux_进程间通信_信号灯
  • 面试--开源框架面试题集合
  • acwing:1576. 再次树遍历
  • dfs 判重Sequence one——hdu 2610
  • 10.4学习
  • 高级java每日一道面试题-2024年10月6日-数据库篇-MVCC是什么? 它的底层原理是什么?
  • SSRF漏洞
  • Java经典面试题-多线程打印
  • js短路求值
  • 网络安全社区和论坛
  • Java入门:10.Java中的包
  • 使用Java调用OpenAI API并解析响应:详细教程
  • 【含文档】基于Springboot+Android的校园论坛系统(含源码+数据库+lw)
  • LeetCode讲解篇之1043. 分隔数组以得到最大和
  • 服装生产管理的现代化:SpringBoot框架
  • 《C++职场中设计模式的学习与应用:开启高效编程之旅》
  • Leetcode.20 有效的括号
  • OpenStreetMap介绍
  • 研发中台拆分之路:深度剖析、心得总结与经验分享
  • Linux_进程概念详解