vue3.0(五) reactive全家桶

文章目录

  • 1 reactive
    • 1.1 reactive的应用
    • 1.2 reactive的特点
    • 1.3 reactive的注意
    • 1.4 reactive的局限性
  • 2 toRefs
  • 3 isReactive
  • 4 shallowReactive
  • 5 readonly
    • 5.1 readonly 详细信息
    • 5.2 readonly函数创建一个只读的响应式对象
    • 5.3 如何修改嵌套在只读响应式对象中的对象?
  • 6 isReadonly
  • 7 shallowReadonly
  • 8 isProxy
  • 总结


1 reactive

1.1 reactive的应用

reactive是另一种声明响应式状态的方式,与将内部值包装在特殊对象中的 ref 不同,reactive() 将使对象本身具有响应性:

import { reactive } from 'vue'
// 声明state
const state = reactive({ count: 0 })
// js中的应用和ref不同不需要value
 console.log(state)
// html模版中应用
 <div>{{ state.count }}</div>

响应式对象是 JavaScript 代理,其行为就和普通对象一样。不同的是,Vue 能够拦截对响应式对象所有属性的访问和修改,以便进行依赖追踪和触发更新。
reactive() 将深层地转换对象:当访问嵌套对象时,它们也会被 reactive() 包装。当 ref 的值是一个对象时,ref() 也会在内部调用它。与浅层 ref 类似,这里也有一个 shallowReactive() API 可以选择退出深层响应性。

1.2 reactive的特点

  • 实现引用类型数据的响应式,如数组、对象等
  • ref去创建引用类型的响应式,其实内部也是调用了reactive
  • reactive创建的响应式对象,调用时不用.value

在Vue3中,reactive函数是用于创建响应式对象的函数。它接收一个普通对象作为参数,返回一个代理对象。这个代理对象可以拦截对象的get和set操作,并在其中实现响应式的逻辑。当我们读取代理对象的属性时,会触发依赖收集;当我们修改代理对象的属性时,会触发相应的依赖更新。在调用reactive函数时,Vue3会使用Proxy对象对传入的对象进行代理,从而实现响应式的特性。

1.3 reactive的注意

  • reactive() 返回的是一个原始对象的 Proxy,它和原始对象是不相等的:
    const obj = {}
    const proxy = reactive(obj)
    // 代理对象和原始对象不是全等的
    console.log(proxy === obj) // false
    
  • 为保证访问代理的一致性,对同一个原始对象调用 reactive() 会总是返回同样的代理对象,而对一个已存在的代理对象调用 reactive() 会返回其本身:
    const obj = {}
    const proxy = reactive(obj)
    // 在同一个对象上调用 reactive() 会返回相同的代理
    console.log(proxy === reactive(obj)) // true
    // 在一个代理上调用 reactive() 会返回它自己
    console.log(reactive(proxy) === proxy) // true
    

1.4 reactive的局限性

  1. 有限的值类型:它只能用于对象类型 (对象、数组和如 Map、Set 这样的集合类型)。它不能持有如 string、number 或 boolean 这样的原始类型。
  2. 不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地“替换”响应式对象,因为这样的话与第一个引用的响应性连接将丢失:
<template>
  <div>{{ state.count }}</div>
  <button @click="mutateDeeply">修改数据</button>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue'
export default defineComponent({
  setup () {
    let state = reactive({ count: 1 })
    console.log(state)
    function mutateDeeply () {
    // 对state进行替换响应式对象
    // 上面的 ({ count: 0 }) 引用将不再被追踪
	// (响应性连接已丢失!)
      state = reactive({ count: 2 })
      console.log(state, state.count)
    }
    return {
      mutateDeeply,
      state
    }
  }
})
</script>

当点击修改数据按钮时,打印的是赋值的数据,但是页面并未更新,(响应性连接已丢失!)

  1. 对解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:
    <template>
      <div>{{ state.count }}</div>
      <button @click="mutateDeeply">修改数据</button>
    </template>
    <script lang="ts">
    import { defineComponent, ref, reactive } from 'vue'
    export default defineComponent({
      setup () {
        const state = reactive({ count: 1 })
        console.log(state)
        function mutateDeeply () {
          // 当解构时,count 已经与 state.count 断开连接
          let { count } = state
          // 不会影响原始的 state
          count++
          console.log(state, state.count, count)
        }
        return {
          container,
          mutateDeeply,
          state
        }
      }
    })
    </script>
    <style scoped>
    </style>
    

上述代码执行结果

2 toRefs

  1. 将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。
     const state = reactive({
       foo: 1,
        bar: 2
      })
      const stateAsRefs = toRefs(state)
      /*
      stateAsRefs 的类型:{
        foo: Ref<number>,
        bar: Ref<number>
      }
      */
    
      // 这个 ref 和源属性已经“链接上了”
      console.log(stateAsRefs) // {foo: ObjectRefImpl, bar: ObjectRefImpl}
      state.foo++
      console.log(stateAsRefs.foo.value)// 2
      stateAsRefs.foo.value++
      console.log(state.foo)// 3
    
    1. 组件可以解构/展开返回的对象而不会失去响应性:
    <template>
      <div>{{ state.foo }}</div>
      <div>{{ state.bar }}</div>
      <button @click="mutateDeeply">修改数据</button>
    </template>
    <script lang="ts">
    import { defineComponent, reactive, toRefs } from 'vue'
    export default defineComponent({
      setup () {
        const state = reactive({
          foo: 1,
          bar: 2
        })
        function useFeatureX () {
          return toRefs(state)
        }
        function mutateDeeply () {
          const { foo, bar } = useFeatureX()
          foo.value++
          bar.value++
          console.log(foo.value, bar.value)
        }
        return {
          mutateDeeply,
          state
        }
      }
    })
    </script>
    <style scoped>
    </style>
    

上述代码执行效果
toRefs 在调用时只会为源对象上可以枚举的属性创建 ref。如果要为可能还不存在的属性创建 ref,请改用 toRef。

3 isReactive

检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。

const state = readonly(reactive({
  count: 1,
  name: 'Tom'
}))

console.log(state.count)// 1
console.log(state.name)// Tom
console.log(isReactive(state)) // true

4 shallowReactive

  1. reactive() 的浅层作用形式。
  2. 和 reactive() 不同,这里没有深层级的转换:一个浅层响应式对象里只有根级别的属性是响应式的。属性的值会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了
<template>
  <div>{{ state.foo }}</div>
  <div>{{ state.nested.bar }}</div>
  <button @click="mutateDeeply">修改数据</button>
</template>
<script lang="ts">
import { defineComponent, shallowReactive, isReactive } from 'vue'
export default defineComponent({
  setup () {
    const state = shallowReactive({
      foo: 1,
      nested: {
        bar: 2
      }
    })
    // ...但下层嵌套对象不会被转为响应式
    console.log(isReactive(state.nested)) // false
    function mutateDeeply () {
      state.foo++
      // 不是响应式的 数据
      state.nested.bar++
      console.log(state.foo, state.nested, state.nested.bar)
    }
    return {
      mutateDeeply,
      state
    }
  }
})
</script>

5 readonly

接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理。

5.1 readonly 详细信息

  • 只读代理是深层的:对任何嵌套属性的访问都将是只读的。它的 ref 解包行为与 reactive() 相同,但解包得到的值是只读的。
  • 要避免深层级的转换行为,请使用 shallowReadonly() 作替代。

5.2 readonly函数创建一个只读的响应式对象

  const state = readonly(reactive({
      count: 1,
      name: 'Tom'
    }))

    console.log(state.count)// 1
    console.log(state.name)// Tom

5.3 如何修改嵌套在只读响应式对象中的对象?

使用readOnly函数创建的只读对象,内部的属性无法修改

   const state = readonly(reactive({
      count: 1,
      name: 'Tom'
    }))

    console.log(state.count)// 1
    state.name = 'diXi' // 输出警告信息,不会触发依赖更新
    console.log(state.name)// Tom

在这里插入图片描述
注意:使用 readonly 函数创建的只读响应式对象是深层只读的。也就是说,当我们尝试修改嵌套在只读响应式对象中的对象时,会输出警告信息,不会触发相应的依赖更新。

6 isReadonly

  • 检查传入的值是否为只读对象。只读对象的属性可以更改,但他们不能通过传入的对象直接赋值。
  • 通过 readonly() 和 shallowReadonly() 创建的代理都是只读的,因为他们是没有 set 函数的 computed() ref。
const state = readonly(reactive({
   count: 1,
   name: 'Tom'
 }))

 console.log(state.count)// 1
 console.log(state.name)// Tom
 console.log(isReadonly(state)) // true

7 shallowReadonly

  • readonly() 的浅层作用形式
  • 和 readonly() 不同,这里没有深层级的转换:只有根层级的属性变为了只读。属性的值都会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。
    const state1 = readonly(reactive({
      foo: 1,
      nested: {
        bar: 2
      }
    }))
    const state = shallowReadonly(reactive({
      foo: 1,
      nested: {
        bar: 2
      }
    }))
    console.log(state.nested.bar++)
    // console.log(state1.nested.bar++) // 报错 Cannot assign to 'bar' because it is a read-only property
    // console.log(state.foo++) // 报错 Cannot assign to 'bar' because it is a read-only property
    // console.log(state1.foo++) // 报错 Cannot assign to 'bar' because it is a read-only property
    // ...但可以更改下层嵌套对象
    isReadonly(state.nested) // false
    

8 isProxy

检查一个对象是否是由 reactive()、readonly()、shallowReactive() 或 shallowReadonly() 创建的代理。

   const state = readonly(reactive({
      count: 1,
      name: 'Tom'
    }))

 console.log(state.count)// 1
 console.log(state.name)// Tom
 console.log(isProxy(state)) // true

总结

Vue3中用于创建响应式对象的三个函数:
reactive、readonly和shallowReactive。
reactive函数用于创建深层响应式对象,
shallowReactive函数用于创建浅层响应式对象,
readonly函数用于创建深层只读响应式对象,
shallowReadonly函数用于创建浅层只读响应式对象。
这些函数可以帮助我们快速创建响应式数据,实现数据的自动更新。
isProxy,isReadonly,isReactive判断是否是相应是对象
isProxy 检查一个对象是否是由 reactive()、readonly()、shallowReactive() 或 shallowReadonly() 创建的代理。
isReadonly 检查传入的值是否为 readonly() 和 shallowReadonly() 创建的只读对象。
isReactive 检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/625933.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

考研数学|李林《880》做不动,怎么办!?看这一篇!

在考研数学的备考过程中&#xff0c;遇到难题是很常见的情况&#xff0c;尤其是当你尝试解决李林880习题集中的问题时。他以其难度和深度著称&#xff0c;旨在帮助考生深入理解数学分析的复杂概念。 如果你在解题过程中感到困难&#xff0c;这并不是你个人的问题&#xff0c;而…

《无畏契约》游戏画面出现“撕裂感“,你清楚背后的原理吗?

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

安全风险 - 如何解决 setAccessible(true) 带来的安全风险?

可能每款成熟的金融app上架前都会经过层层安全检测才能执行上架&#xff0c;所以我隔三差五就能看到安全检测报告中提到的问题&#xff0c;根据问题的不同级别&#xff0c;处理的优先级也有所不同&#xff0c;此次讲的主要是一个 “轻度问题” &#xff0c;个人认为属于那种可改…

[译文] 恶意代码分析:2.LNK文件伪装成证书传播RokRAT恶意软件(含无文件攻击)

这是作者新开的一个专栏&#xff0c;主要翻译国外知名安全厂商的技术报告和安全技术&#xff0c;了解它们的前沿技术&#xff0c;学习它们威胁溯源和恶意代码分析的方法&#xff0c;希望对您有所帮助。当然&#xff0c;由于作者英语有限&#xff0c;会借助LLM进行校验和润色&am…

idea控制台日志控制

1.清除控制台log日志 测试的时候&#xff0c;控制台打印的日志比较多&#xff0c;速度有点慢而且不利于查看运行结果&#xff0c;所以接下来我们把这个日志处理下: 取消初始化spring日志打印&#xff0c;resources目录下添加logback.xml&#xff0c;名称固定&#xff0c;内容如…

Transformer+Classification学习笔记

论文名称&#xff1a;An Image is Worth 16x16 Words:Transformers for Image Recognition at Scale [2112.11010] MPViT: Multi-Path Vision Transformer for Dense Prediction (arxiv.org) 参考博客与视频&#xff1a; Vision Transformer 超详细解读 (原理分析代码解读) …

[动画详解]LeetCode151.翻转字符串里的单词

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到动画详解LeetCode算法系列 用通俗易懂的动画让算法题不再神秘 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成…

589.N叉树的前序遍历

刷算法题&#xff1a; 第一遍&#xff1a;1.看5分钟&#xff0c;没思路看题解 2.通过题解改进自己的解法&#xff0c;并且要写每行的注释以及自己的思路。 3.思考自己做到了题解的哪一步&#xff0c;下次怎么才能做对(总结方法) 4.整理到自己的自媒体平台。 5.再刷重复的类…

解决el-upload组件上传文件403 Forbidden的问题

话不多说&#xff0c;上错误。网络显示&#xff1a; 控制台显示&#xff1a; 并且后端也没接收到任何的请求。 只需要把前端中的组件&#xff1a; action的路径修改为&#xff1a; 也就是不写前面的localhost&#xff0c;而是拼接上发送请求拼接的‘api’即可 可以看到&#x…

架构每日一学 6:作为架构师,你必须学会寻找商业模式

本文首发于公众平台&#xff1a;腐烂的橘子 在前面的文章中&#xff0c;我们已经讲了架构师的两条生存法则&#xff0c;第一条是有且仅有一个目标&#xff0c;感兴趣的可以看一下原文&#xff1a; 架构每日一学 2&#xff1a;架构师六个生存法则之一&#xff1a;架构必须有且仅…

【LLM第五篇】名词解释:prompt

1.是什么 提示工程&#xff08;Prompt Engineering&#xff09;是一门较新的学科&#xff0c;关注提示词开发和优化&#xff0c;帮助用户将大语言模型&#xff08;Large Language Model, LLM&#xff09;用于各场景和研究领域。 掌握了提示工程相关技能将有助于用户更好地了解…

教育型内容的制胜秘诀:Kompas.ai如何结合知识与营销

在数字化营销的浪潮中&#xff0c;教育型内容已经成为品牌建立权威性和提供价值的重要手段。通过分享专业知识和见解&#xff0c;品牌不仅能够吸引目标受众&#xff0c;还能够在潜在客户心中建立起专业和可信赖的形象。本文将深入分析教育型内容的重要性&#xff0c;详细介绍Ko…

sklearn之k近邻算法——以鸢尾花分类为例

文章目录 k近邻算法算法原理k值的选取特征数据的归一化距离的度量分类原则的制定鸢尾花分类 k近邻算法 k近邻算法是经典的监督学习算法&#xff0c;我们这里主要介绍k近邻算法的基本内容和如何应用 算法原理 k近邻算法的基本原理其实很简单 首先k近邻算法是一个分类算法&am…

x264 帧类型代价计算原理:slicetype_slice_cost 函数分析

x264 x264 是一个开源的视频编码库,它实现了H.264/AVC标准。H.264是一种广泛使用的压缩标准,用于视频流、视频下载、蓝光光盘以及许多其他形式的数字视频分发。x264 以其高压缩效率和良好的视频质量而著称,是许多视频编辑软件和视频播放器的默认编解码器。 以下是关于 x26…

软件工程期末复习(6)需求分析的任务

需求分析 需求分析的任务 “建造一个软件系统的最困难的部分是决定要建造什么……没有别的工作在做错时会如此影响最终系统&#xff0c;没有别的工作比以后矫正更困难。” —— Fred Brooks 需求难以建立的原因&#x…

半小时搞懂STM32面经知识——RCC

1. 时钟的概念 时钟是由电路产生的具有周期性的脉冲信号&#xff0c;相当于单片机的心脏&#xff0c;要想使用单片机的外设必须开启时钟。 时钟对单片机有什么作用&#xff1f; 1. 驱动外设的本质是寄存器&#xff0c;而寄存器需要时钟触发才能改写值。 2. 时钟频率越高&#…

基于Docker的JMeter分布式压测

一个JMeter实例可能无法产生足够的负载来对你的应用程序进行压力测试。如本网站所示&#xff0c;一个JMeter实例将能够控制许多其他的远程JMeter实例&#xff0c;并对你的应用程序产生更大的负载。JMeter使用Java RMI[远程方法调用]来与分布式网络中的对象进行交互。JMeter主站…

前端已死? Bootstrap--JS-jQuery

目录 Bootstrap--JS-jQuery 1 jQuery基础 介绍 基础语法&#xff1a; $(selector).action() 1.1 安装jQuery 地址 基础语法&#xff1a; $(selector).action() 2 jQuery事件 事件处理程序指的是当 HTML 中发生某些事件时所调用的方法。 jQuery常用事件 2.1 鼠标事件…

栅格地图、障碍物地图与膨胀地图(障碍物地图(三)写一张障碍物地图)

花了不少时间看完了障碍物地图的大致思路&#xff0c;这里简单根据前面的思路来写一个简易版的障碍物地图。 1.订阅一张地图 首先&#xff0c;我们需要一张静态地图作为原始数据&#xff0c;这个我们可以订阅当前的map来获取&#xff1a; void map_test1::MapCallback(const…

软件库V1.5版本iApp源码V3

软件库V1.5版本iApp源码V3 配置教程在【mian.iyu】的【载入事件】 更新内容&#xff1a; 1、分类对接蓝奏&#xff08;免费&#xff0c;付费&#xff0c;会员&#xff0c;广告&#xff09;&#xff0c;支持蓝奏文件描述设置为简介&#xff08;改动&#xff1a;首页.iyu&#…