【vue】08.vue的响应式原理

一.什么是响应式数据

响应式数据是指那些能够在被修改时自动更新视图的数据。在 Vue.js 中,响应式数据是核心特性之一,它允许开发者通过简单地修改数据来驱动界面更新,无需手动操作 DOM。当响应式数据的值发生变化时,所有依赖于这些数据的视图都会自动重新渲染,以反映最新的状态。

简单来说,响应式数据就是会自动更新到界面上的数据。

二.基于Proxy实现响应式

Vue 3 使用 Proxy 来拦截对象的读取(get)和设置(set)操作。

  1. 拦截读取操作:当访问一个属性时,Proxy 可以拦截这个操作,并记录下这次访问,以便将来数据变化时可以进行通知。
  2. 拦截设置操作:当修改一个属性时,Proxy 可以拦截这个操作,并更新数据的同时通知所有依赖于这个属性的视图或副作用函数。

如果把响应式数据比喻为一个随时可更新的资料,那么proxy就是看守这份资料的人,当有人需要看(读取get)这份资料时,中间人(proxy)会记录下来者的名字,并将其放入来访者名单中。

若有人修改(设置set)了这份资料的内容,中间人(proxy)也会通知之前所有来者进行更新,保证之前的来者都能拿到最新的数据。

那么这里面又涉及两个专业名词,依赖收集和副作用函数。

1.依赖收集

访问数据时,响应式系统会记录这次访问,即“依赖收集”。

也就是例子中的:记入名单中。

每个响应式属性都有一个依赖列表,记录了所有使用该属性的副作用(比如组件的渲染函数)。

2.副作用函数

副作用函数是指在响应式数据变化时需要执行的函数。

当响应式数据变化时,响应式系统会找到依赖该数据的所有副作用函数并执行它们。

比如说资料1 里记录我们班一共有30个人,资料2记录我们年纪一共1000人(每班人数相加),这时候我们班新来一个同学,导致资料1中的人数变为31人,那么proxy就会通知所有像资料2一样用到资料1的资料(这些用到30进行计算的过程,叫做副作用函数),说现在是31人了,你们得重新计算。

3.get 和 set

基本的过程搞清楚后,就可以看看get和set在代码中的使用了。

var obj = new Proxy({}, {
  // get函数,接收两个参数(目标对象,要访问的属性)
  get: function (target, name) {
    return name;
  },
  // set函数,接收三个参数(目标对象,要修改的属性,要修改的值)
  set: function (target, key, val) {
    target[key] = val
    return target;
  }
});

三.ref( ) 和 reactive( )

ref 和 reactive 都用于创建响应式数据。但是它们在用法上有一些区别。

1.ref

  • 用途ref 用于定义一个响应式的数据源,通常用于基本数据类型(如 StringNumberBoolean)。
  • 返回值ref 返回一个包含响应式数据的对象,该对象具有一个 .value 属性,用于访问或修改内部值。
  • 用法
import { ref } from 'vue';

const count = ref(0); // 创建一个响应式数据,初始值为 0

console.log(count.value); // 输出:0
count.value++; // 修改值
console.log(count.value); // 输出:1

2.reactive

  • 用途reactive 用于创建一个响应式对象,适用于复杂数据结构(如对象、数组)。
  • 返回值reactive 直接返回一个响应式对象,不需要通过 .value 属性来访问或修改数据。
  • 用法
import { reactive } from 'vue';

const state = reactive({
  count: 0
}); // 创建一个响应式对象

console.log(state.count); // 输出:0
state.count++; // 修改值
console.log(state.count); // 输出:1

3.区别

  • 类型ref 通常用于基本数据类型,而 reactive 用于对象和数组。
  • 访问方式:使用 ref 创建的响应式数据需要通过 .value 属性来访问和修改,而 reactive 创建的响应式数据则可以直接访问和修改属性。
  • 解包:在模板中,Vue 会自动解包 ref,所以不需要使用 .value。但在 JavaScript 中,仍然需要使用 .value
<template>
  <div>{
   
   { count }}</div> <!-- 在模板中自动解包,不需要.value -->
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);
    console.log(count.value);
    return { count };
  }
}
</script>

四.响应式核心原理

上面其实已经给出了响应式的原理,这部分主要是对上面的内容进行总结与梳理。

Vue 3 的响应式核心原理分为四个步骤:

  1. 代理:通过 Proxy 对原始数据进行代理,以便拦截数据的读取和修改操作。
  2. 依赖收集:当数据被读取时,Vue 会记录下这次读取操作,即收集依赖。这样,当数据变化时,Vue 知道哪些视图或函数需要被通知。
  3. 变更检测:当数据被修改时,Proxy 会检测到这个变化,并触发更新流程。
  4. 通知更新:Vue 会通知所有依赖于这个数据的视图或副作用函数进行更新,从而实现数据的变更到视图的自动同步。

一周又一周,今天又到周五了,期待下班!!!