浅析Vue为什么需要同时使用Ref和Reactive

 更新时间:2023年08月09日 08:44:30   作者:王大冶  
这篇文章主要想来和大家一起探讨一下Vue为什么需要同时使用Ref和Reactive,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起了解一下

在使用 Options API 工作时声明响应性数据是直截了当的。data 选项内的所有内容都会自动变为响应性,并在模板中可用。唯一需要注意的是,要将data设为一个函数,以防止在所有组件实例之间共享状态。

让我们讨论一下Vue 3中发生了什么变化,以及为什么我们需要两个不同的助手。

Vue 2中的响应性

data 组件选项内的每个属性都将通过 Object.defineProperty 转换为getter/setter。这些getter/setter对我们来说是看不见的,但在底层,它们使Vue在访问或修改属性时能够执行依赖跟踪。

每个组件都有一个关联的观察者,用于跟踪在组件的渲染周期中使用的属性。如果依赖项更新,观察者会通知组件,然后触发重新渲染。

Vue 3中的响应性

在 Vue 3 中,一切都发生了变化。核心部分从零开始重写,现在由Javascript Proxies提供响应性。Proxies是一种现代且优雅的方式来观察一个对象并在其属性被访问或更新时得到通知。

可以通过以下简单的例子来理解代理是如何工作的:

const userInfo = {
  firstName: "fotis",
  age: 35,
};
const handler = {
  get(target, property) {
    if (property === "firstName") {
      const name = target[property]
      return name.charAt(0).toUpperCase() + name.slice(1);
    }
    if (property === "age") {
      return '--'
    }
    return target[property]
  },
};
const proxy = new Proxy(userInfo, handler);
console.log(proxy.firstName) // "Fotis"
console.log(proxy.age) // "--"

处理器内部的get方法被称为陷阱,每次访问对象的属性时都会被调用。以类似的方式,可以定义一个设定的陷阱:

const userInfo = {
  firstName: "Fotis",
  age: 35,
};
const handler = {
  set(target, prop, value) {
    if (prop === "age") {
      if (!Number.isInteger(value)) {
        throw new TypeError("The age is not an integer");
      }
      if (value > 200) {
        throw new RangeError("The age seems invalid");
      }
    }
    target[prop] = value;
    return true;
  },
};
const proxy = new Proxy(userInfo, handler);
proxy.age = 12 // OK
proxy.age = 300 // Error: The age seems invalid

这正是 Vue 3 响应性背后的理念。当使用 reactive 助手声明一个变量时,会使用一个 proxy. 来跟踪任何变化。

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key)
      return target[key]
    },
    set(target, key, value) {
      target[key] = value
      trigger(target, key)
    }
  })
}

当然,响应式助手的实际实现更为复杂,能处理边缘情况,但其核心仍然使用proxy。

以上的片段解释了为什么将响应性变量解构或重新分配给本地变量后,它就不再具有反应性,因为它不再触发源对象上的 get/set proxy 陷阱。

这看起来像是一个完美的解决方案,可以使所有事物都变成响应式。但是有个问题!根据定义,proxy只适用于复杂类型。这些包括对象、数组、映射和集合。要使一个原始类型变得反应灵敏,我们仍然需要使用代理,但首先我们必须将其包装在一个对象中。

function ref(value) {
  const refObject = {
    get value() {
      track(refObject, 'value')
      return value
    },
    set value(newValue) {
      value = newValue
      trigger(refObject, 'value')
    }
  }
  return refObject
}

这解释了为什么必须在 script setup 中使用烦人的 .value 。而且,再次重构或重新分配给本地变量也是行不通的。

总结

那么,为什么需要 Ref 和 Reactive的答案是:Proxy。对于复杂类型,它们可以直接使用,但对于原始类型,需要创建一个代理对象。

希望,理解Vue的内部工作原理可以使你更有效,并且可以消除 refreactive 之间的任何混淆。

以上就是浅析Vue为什么需要同时使用Ref和Reactive的详细内容,更多关于Vue Ref Reactive的资料请关注脚本之家其它相关文章!

相关文章

  • vue3 座位选座矩阵布局的实现方法(可点击选中拖拽调换位置)

    vue3 座位选座矩阵布局的实现方法(可点击选中拖拽调换位置)

    由于公司项目需求需要做一个线上设置考场相关的座位布局用于给学生考机排号考试,实现教室考场座位布局的矩阵布局,可点击选中标记是否有座无座拖拽调换位置横向纵向排列,本文给大家分享实现代码,一起看看吧
    2023-11-11
  • vue 父组件获取子组件里面的data数据(实现步骤)

    vue 父组件获取子组件里面的data数据(实现步骤)

    在Vue中,父组件可以通过`ref`引用子组件,并通过`$refs`属性来访问子组件的数据,下面分步骤给大家介绍vue 父组件获取子组件里面的data数据,感兴趣的朋友一起看看吧
    2024-06-06
  • Vue实现PC端靠边悬浮球的代码

    Vue实现PC端靠边悬浮球的代码

    这篇文章主要介绍了Vue实现靠边悬浮球(PC端)效果,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • 在Vue3中实现懒加载功能的代码示例

    在Vue3中实现懒加载功能的代码示例

    在现代前端开发中,懒加载是一种提高应用性能和用户体验的重要技术,尤其是在处理较大图片或长列表数据时,本文将使用 Vue 3 和其新推出的 setup 语法糖来实现懒加载功能,并提供具体的示例代码,需要的朋友可以参考下
    2024-09-09
  • vuex实现数据状态持久化

    vuex实现数据状态持久化

    今天小编就为大家分享一篇vuex实现数据状态持久化,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • 2种在vue项目中使用百度地图的简单方法

    2种在vue项目中使用百度地图的简单方法

    在本篇文章中我们给大家整理了2种关于VUE项目中使用百度地图的最简单的方法,非常实用,一起来学习下。
    2018-09-09
  • vue父组件异步如何获取数据传给子组件

    vue父组件异步如何获取数据传给子组件

    这篇文章主要介绍了vue父组件异步如何获取数据传给子组件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • 在vue项目中安装使用Mint-UI的方法

    在vue项目中安装使用Mint-UI的方法

    Mint UI 是 由饿了么前端团队推出的 一个基于 Vue.js 的移动端组件库,下面通过本文给大家介绍在vue项目中安装使用Mint-UI的方法,需要的朋友参考下吧
    2017-12-12
  • 解决vue项目中某一页面不想引用公共组件app.vue的问题

    解决vue项目中某一页面不想引用公共组件app.vue的问题

    这篇文章主要介绍了解决vue项目中某一页面不想引用公共组件app.vue的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • VUE生命周期全面系统详解

    VUE生命周期全面系统详解

    Vue的生命周期就是vue实例从创建到销毁的全过程,也就是new Vue() 开始就是vue生命周期的开始。Vue 实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 等⼀系列过程,称这是Vue的⽣命周期
    2022-07-07

最新评论