一步步从Vue3.x源码上理解ref和reactive的区别

yizhihongxing

当我们在使用Vue3.x的时候,ref和reactive这两个API很常用,但是也经常容易搞混。这篇攻略将介绍ref和 reactive的区别,并且通过源码分析来更加深刻理解这两者之间的差异。

1. reactive

reactive是用于将对象转为响应式的API。我们一般使用这个API来将普通的对象转成可以响应式地监听的对象。使用方法如下所示:

import { reactive } from 'vue'

const reactiveObject = reactive({
  count: 1
})

从上面的代码中,我们可以看出,将对象传给 reactive()后会返回一个通过 Proxy实现的响应式对象,而这个响应式对象可以监听到它自身属性的变化。

2. ref

ref是用来定义一个响应式数据的API。如果我们的目标只是一个基本类型的变量或者只需要进行单向绑定,则可以选择使用ref。下面是使用ref的例子:

import { ref } from 'vue'

const count = ref(1)

从上面代码中,我们可以看出,ref会接收一个基本类型的数据,例如数值、字符串等,然后返回一个响应式对象。这个响应式对象有一个 .value的属性,通过 .value属性获取到的就是我们传入ref()的值。

3. ref和reactive的区别

  • ref是针对基本类型变量的响应式处理,reactive是针对对象类型的响应式处理。
  • ref返回的对象具有 .value 属性,而reactive返回整个对象。
  • ref可以修改基本类型的值,而reactive不能直接修改对象属性的值,只能使用 .value或者 toRefs来修改。

下面通过源代码来进一步理解这两者的区别。

import { ref, reactive } from 'vue'

const stateA = {
  count1: ref(1),
  count2: 2,
  countObj: reactive({
    count: 3
  })
}

stateA.count1++  // 可以直接修改数值类型

stateA.count2++  // 修改会报错,需要使用reactive

stateA.countObj.count++  // 可以直接修改reactive对象属性

通过上面这段代码可以看出,在对象中,对象属性的直接修改仅仅适用于reactive对象,而针对基本类型的变量则可以使用ref。至于为什么可以这样,我们可以通过源码来分析。

4. 源码分析

首先我们来看ref的源码:

export function ref(value) {
  // 对基本类型的值进行处理
  return createRef(value)
}

function createRef(rawValue, shallow = false) {
  if (isRef(rawValue)) {
    return rawValue
  }
  const value = shallow ? rawValue : convert(rawValue)
  const runner = effect(() => {
    if (!isRef(runner)) {
      runner.value = value.value
    }
  }, {
    lazy: true,
    scheduler: shallow ? () => {} : triggerRef
  })
  const ref = {
    _isRef: true,
    get value() {
      trackRefValue(ref)
      return value
    },
    set value(newVal) {
      if (hasChanged(toRaw(newVal), rawValue)) {
        rawValue = newVal
        value.value = shallow ? newVal : convert(newVal).value
        triggerRef(ref)
      }
    }
  }
  return ref
}

从源码中可以看到,ref是通过 createRef 实现的,这个函数是设置基础类型数据的响应式的。

然后我们看reactive 的源码:

export function reactive(target) {
  if (target && target._isReadonly) {
    return target
  }
  // 如果target已经被处理过为响应式的,则直接返回target
  if (reactiveMap.has(target)) {
    return reactiveMap.get(target)
  }
  // 如果target是ref,则直接返回.value对应的响应式对象
  if (target && target.__v_isRef) {
    return reactive(target.value)
  }
  const observed = new Proxy(target, baseHandlers)
  reactiveMap.set(target, observed)
  return observed
}

从源码中可以看到,reactive 是通过创建新的 Proxy 对象来实现对象的响应式的。当 getset对象属性时,替换成监听 tracktrigger

基于这些源代码,我们可以得出refreactive的差异:

  • ref创建了一个对象,并通过这个对象的getter和setter来监听反应式数据的变化;
  • Reactive将一个对象变为响应式对象,并将其对象的所有属性都转为getter和setter来监听反应式数据的变化;

这就是ref和reactive之间的区别。对于基础类型数据,可以使用ref进行设置响应式;对于对象类型数据可以使用reactive设置响应式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一步步从Vue3.x源码上理解ref和reactive的区别 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • 15分钟上手vue3.0(小结)

    15分钟上手vue3.0(小结) 介绍 Vue.js 3.0 是一个轻量级的框架,易于学习和使用。它具有高效、灵活、高度可定制性等优点,而且我们可以通过官方文档、社区论坛等方式快速掌握其使用方法。 本文将带领大家了解并上手 Vue.js 3.0。 安装 Vue.js 3.0 在开始使用 Vue.js 3.0 之前,我们需要先安装它。我们可以通过以下方式进行安…

    Vue 2023年5月28日
    00
  • Vue.js 应用性能优化分析+解决方案

    当一个 Vue.js 应用规模变大时,常常需要考虑其性能问题,以保证用户体验。本文将提供详细的 Vue.js 应用性能优化分析和解决方案,包括以下步骤: Step 1:性能测试 在优化之前,需要对应用做性能测试,以找出需要优化的部分和瓶颈。可以使用浏览器自带的性能分析器,在 Vue.js 开发调试时可使用 Vue Devtools 插件进行组件性能分析。 S…

    Vue 2023年5月27日
    00
  • 记一次用ts+vuecli4重构项目的实现

    让我来详细讲解一下“记一次用TypeScript + Vue CLI 4重构项目”的完整攻略。 准备工作 在进行 TypeScript 重构之前,需要先安装必要的工具和依赖库。以下是准备工作的步骤: 安装 Node.js。 安装 Vue CLI 4。 npm install -g @vue/cli 创建一个新的 Vue 项目,并选择 TypeScript 选…

    Vue 2023年5月28日
    00
  • vue + Electron 制作桌面应用的示例代码

    下面是关于“vue + Electron 制作桌面应用的示例代码”的完整攻略,主要分为以下几个步骤: 1. 创建项目 首先,确保已安装最新版本的 nodejs 和 npm。然后,在命令行工具中输入以下命令创建一个基础的 Vue.js 项目。 vue create my-desktop-app 接下来,进入项目目录并安装 Electron 和 electron…

    Vue 2023年5月27日
    00
  • 实时通信Socket io的使用示例详解

    实时通信Socket io的使用示例详解 Socket.io是一个基于WebSockets的实时通信协议,可以让浏览器和服务器之间建立长连接,实现实时的双向通信。下面将详细介绍Socket.io使用示例。 安装Socket.io 首先需要在服务器环境中安装Socket.io。可以通过npm进行安装,执行以下命令: npm install socket.io …

    Vue 2023年5月28日
    00
  • Vue动态组件实现异常处理方法

    下面就是Vue动态组件实现异常处理的完整攻略: 1. Vue动态组件介绍 Vue的动态组件是指通过动态地绑定组件的名称来实现动态加载不同组件的技术。Vue动态组件是Vue.js框架中的一项重要功能,它允许开发人员将应用程序拆分为基本组件,并根据需要在组件之间进行动态转换。 2. Vue中异常处理的重要性 在开发过程中,难免会出现各种各样的异常错误,如组件的数…

    Vue 2023年5月28日
    00
  • Vue生命周期区别详解

    首先,需要了解Vue的生命周期是什么。Vue生命周期是Vue实例从创建到销毁的过程,在其中它会依次经过不同的状态和调用不同的钩子函数。Vue的生命周期分为8个阶段,分别是: beforeCreate: 在实例初始化之后,数据观测和初始化事件之前调用。 created: 在实例创建完成后调用,此阶段完成了数据观测和属性计算,但尚未开始真正的DOM相关操作。 b…

    Vue 2023年5月28日
    00
  • 解决vue select当前value没有更新到vue对象属性的问题

    我将为您详细讲解“解决Vue Select当前Value没有更新到Vue对象属性的问题”的完整攻略。 简介 在Vue开发中,我们通常会使用Vue Select组件来实现下拉选择框。但是在使用过程中,会发现Vue Select的value属性不能够及时更新到Vue对象中的属性,导致无法实现数据的双向绑定。本文将为大家提供解决这个问题的完整攻略。 解决方案 解决…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部