首页 > 其他分享 >vue3-ref 和 reactive

vue3-ref 和 reactive

时间:2024-10-30 21:17:59浏览次数:7  
标签:count 响应 对象 value reactive vue3 ref

文章目录

vue3 中 ref 和 reactive

  1. ref原理
    • 基本原理
      • ref是Vue 3中用于创建响应式数据的一个函数。它的基本原理是通过Object.defineProperty()(在JavaScript的规范中用于定义对象属性的方法)或者Proxy(ES6新特性,用于创建对象的代理)来实现数据的响应式。当数据被修改时,它会触发更新相关的副作用函数(例如更新DOM等操作)。
      • 当使用ref创建一个响应式数据时,它实际上返回一个包含value属性的对象。例如,const count = ref(0),这里的count是一个对象,访问和修改数据需要通过count.value
    • 底层实现细节(简单示例)
      • 以下是一个简单的模拟ref实现的代码(简化版,实际Vue 3代码更复杂):
function ref(raw) {
    const r = {
        get value() {
            track(r, 'value');
            return raw;
        },
        set value(newVal) {
            if (newVal!== raw) {
                raw = newVal;
                trigger(r, 'value');
            }
        }
    };
    return r;
}
 - 这里的`track`函数用于收集依赖(记录哪些函数依赖了这个`ref`数据),`trigger`函数用于触发更新(当数据改变时,通知依赖的函数重新执行)。
  1. reactive原理
    • 基本原理
      • reactive是基于Proxy对象来实现响应式的。Proxy可以拦截对目标对象的各种操作,如读取属性、设置属性、删除属性等。当这些操作发生时,reactive可以触发相应的更新逻辑。
      • 例如,const state = reactive({ count: 0 }),对state.count的读取和修改都会被Proxy拦截,从而实现响应式。
    • 底层实现细节(简单示例)
      • 以下是一个简单的模拟reactive实现的代码片段(简化版):
function reactive(target) {
    return new Proxy(target, {
        get(target, key, receiver) {
            track(target, key);
            return Reflect.get(target, key, receiver);
        },
        set(target, key, value, receiver) {
            const result = Reflect.set(target, key, value, receiver);
            trigger(target, key);
            return result;
        }
    });
}
 - 同样,这里的`track`和`trigger`函数用于收集依赖和触发更新,和`ref`的原理类似,但是`reactive`是针对整个对象的属性进行拦截。
  1. ref和reactive的应用场景

    • ref应用场景
      • 基本数据类型:当处理基本数据类型(如numberstringboolean)的响应式数据时,通常使用ref。例如,一个计数器const count = ref(0),这里count是一个ref对象,通过count.value来访问和修改计数值。
      • 在组合式API中传递单个数据:如果在组合式API函数之间传递一个简单的响应式数据,ref是一个很好的选择。比如一个函数返回一个ref数据,另一个函数可以接收并使用这个ref
    • reactive应用场景
      • 复杂对象类型:对于复杂的对象(如包含多个属性的对象或数组),使用reactive更为合适。例如,const state = reactive({ name: 'John', age: 30, hobbies: ['reading', 'coding']}),对state对象中的任何属性的访问和修改都会是响应式的。
      • 多个相关数据的管理:当需要管理一组相关的数据并且希望它们作为一个整体进行响应式处理时,reactive是首选。比如一个表单数据对象,包含表单的各个字段值,使用reactive可以方便地处理整个表单数据的更新和响应。
  2. 应用要求/依据

    • 响应式数据的修改原则
      • 对于ref,必须通过.value属性来修改数据才能触发响应式更新。例如,count.value++会触发更新,而直接count = new_value(这里countref)不会触发响应式更新。
      • 对于reactive,直接修改对象的属性就可以触发响应式更新。如state.name = 'Jane'(这里statereactive对象)会触发更新。
    • 模板中的使用差异
      • 在Vue 3的模板中,ref的数据可以直接在模板中使用,不需要额外的.value语法。例如,<div>{{ count }}</div>(这里countref)是可以正常工作的,Vue会自动处理value属性的访问。而对于reactive对象,直接通过属性访问即可,如<div>{{ state.name }}</div>(这里statereactive对象)。

reactive 与 ref 不同之处

  1. 数据类型处理方式不同
    • ref
      • 主要用于包装基本数据类型(如numberstringboolean),使其具有响应式特性。例如const count = ref(0)count是一个对象,它有一个value属性来存储实际的数据。在JavaScript代码中,必须通过count.value来访问和修改这个数据。
    • reactive
      • 用于处理复杂的对象类型(如对象字面量或数组),它会递归地将对象的所有属性转换为响应式。例如const state = reactive({ count: 0, message: 'Hello'})state本身就是响应式对象,对state.countstate.message等属性的访问和修改都是响应式的,不需要像ref那样通过特定的value属性来操作。
  2. 在模板中的使用差异
    • ref
      • 在Vue 3模板中使用ref时,不需要显式地访问value属性。Vue会自动进行解包,例如,如果count是一个ref,在模板中可以直接写成<div>{{ count }}</div>,它会正确地渲染count.value的值。
    • reactive
      • 对于reactive对象,在模板中直接通过属性访问来使用。如const state = reactive({ name: 'John'}),在模板中可以写成<div>{{ state.name }}</div>来显示name属性的值。
  3. 响应式转换的深度不同
    • ref
      • 只对它包装的那个数据本身进行响应式处理。如果ref包装了一个对象,它不会自动将对象内部的属性也转换为响应式,仍然需要通过value属性来访问对象,并且如果要使对象内部属性具有响应式,可能还需要进一步的处理(如使用reactive来处理这个对象)。
    • reactive
      • 是深度响应式的。当使用reactive处理一个对象时,它不仅会使对象本身的属性具有响应式,还会递归地将对象内部嵌套的对象和数组的属性也转换为响应式。例如,如果有一个对象const user = reactive({ name: 'Alice', address: { city: 'New York', street: '123 Main St' }}),那么user.address.city的访问和修改也是响应式的。
  4. 创建和使用的语法及场景差异
    • ref
      • 创建语法简单直接,适用于单个数据值的响应式处理,特别是基本数据类型。在组合式API中,当需要从一个函数返回一个响应式数据,并且这个数据是基本类型或者只需要简单的包装时,ref是很好的选择。
    • reactive
      • 创建时需要传入一个对象,更适合处理复杂的、有多个相关属性的数据结构,如应用程序中的状态对象。当有一组相关的数据需要作为一个整体进行响应式管理时,如表单数据、应用的全局状态等,reactive是更合适的方式。

ref 处理复杂类型

  1. ref处理复杂类型

    • 从功能上来说,ref可以用来包装复杂的数据类型,如对象或数组。例如,可以使用ref创建一个包含多个属性的对象,const myObject = ref({name: 'John', age: 30})
  2. 限制

    • 访问方式的限制
      • 在JavaScript代码中,必须通过value属性来访问和修改包装后的复杂对象。例如,要访问上述myObject中的name属性,需要使用myObject.value.name。这与reactive不同,reactive可以直接通过属性访问(如const myReactiveObject = reactive({name: 'Alice'}); myReactiveObject.name)。这种访问方式的差异可能会导致代码不够简洁直观,尤其是在处理多层嵌套的复杂对象时。
    • 响应式转换深度的限制
      • ref本身不会对包装的复杂对象内部进行深度的响应式转换。例如,如果有一个ref包装的对象const user = ref({name: 'Bob', address: {city: 'New York'}}),修改user.value.address.city不会自动触发响应式更新,除非address这个对象本身也经过了响应式处理(如使用reactive来处理address对象)。而reactive会自动对对象内部进行深度响应式处理。
    • 在模板中的限制(部分)
      • 在Vue 3的模板中,ref包装的复杂对象在某些情况下可能会引起混淆。虽然Vue会自动展开ref的值,但对于复杂对象的属性访问,有时候可能需要注意绑定的语法。例如,如果要在模板中使用myObject中的name属性,写成{{myObject.name}}是不行的,需要写成{{myObject.value.name}},不过Vue在模板渲染时会自动处理refvalue属性,使得在大多数简单情况下可以像使用普通数据一样使用ref包装的数据。但在复杂的模板绑定场景下,还是要注意正确的语法。

标签:count,响应,对象,value,reactive,vue3,ref
From: https://blog.csdn.net/m0_51244077/article/details/143375211

相关文章

  • Vue3中前台前端解决方案速记
    WebpackVSVite:Webpack默认构建整个应用;稳妥Vite只构建必须构建的内容;以原生ESM方式提供源码,让浏览器构建;快用Vite创建一个项目:[email protected]@latest在局域网内运行项目:package.json"scripts":{"dev":"vite--host",在Vite项目中安装tailwindcss:......
  • (系列十)Vue3中菜单和路由的结合使用,实现菜单的动态切换(附源码)
    说明  该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。   该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。   说明:OverallAuth2.0是一个简单、易懂、功能强大的权限+可视化流程管理系统。友情提醒:本篇文章是属于系......
  • vue2使用vue3语法
    CompositionAPICompositionAPI将是Vue3的核心功能,它具有许多更改和性能改进。我们也可以在Vue2中通过npm插件@vue/composition-api使用它。安装yarnadd@vue/composition-api之后,在入口文件main.js中使用它。importVuefrom'vue'importVueCompositionAPI......
  • 《vue3第五章》新的组件,包含:Fragment、Teleport、Suspense
    @目录五、新的组件1.Fragment2.Teleport案例完整代码3.Suspense案例完整代码本人其他相关文章链接五、新的组件1.Fragment在Vue2中:组件必须有一个根标签在Vue3中:组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中好处:减少标签层级,减小内存占用2......
  • 《vue3第六章》其他,包含:全局API的转移、其他改变
    @目录六、其他1.全局API的转移2.其他改变六、其他1.全局API的转移Vue2.x有许多全局API和配置。例如:注册全局组件、注册全局指令等。//注册全局组件Vue.component('MyButton',{data:()=>({count:0}),template:'<button@click="count++">Clicke......
  • 《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API
    @目录四、CompositionAPI的优势1.OptionsAPI存在的问题2.CompositionAPI的优势四、CompositionAPI的优势1.OptionsAPI存在的问题使用传统OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改。CompositionAPI的优势-图1.gifComposition......
  • vue3知识点:Teleport组件
    @目录五、新的组件2.Teleport案例完整代码本人其他相关文章链接五、新的组件2.Teleport问题:什么是Teleport? 答案:Teleport是一种能够将我们的组件html结构移动到指定位置的技术。<teleportto="移动位置"> <divv-if="isShow"class="mask"> <divclass="dialog"> &l......
  • VUE3+signalR实现单点登录
    摘要:在MES项目中,不能多人同时操作,方便任务分配追责,使用signalR实现单点登录1、在项目中安装依赖npmi@microsoft/signalr2、使用:在登录成功的时候与服务器建立连接//登录和服务器建立连接、实现单点登录conststartConnection=async(res:any)=>{try{......
  • 解决:swagger2 Could not resolve reference because of: Could not resolve pointer:
    问题:使用swagger时页面出现报警信息mavaen依赖版本:2.8.0<!--swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.8.0<......
  • Vue3 - 完美解决html2canvas截图不全问题,截图只截取当前可视区域导出图片不全,截屏导出
    前言该解决方案任意前端技术栈通用,不仅限Vue。在vue3(手机H5移动端/微信公众号H5页面)项目开发中,使用html2canvas截屏时发现有一部分未截取到少了一块截图不完整,导出保存图片时发现截图只有一半显示不全,另外还有一个问题就是截图时截取当前可视区域的问题(出现滚动条只保......