Vue3中的组合Api与响应函数

news2024/11/30 8:40:16

文章目录

  • 1. 组合Api介绍
    • setup
  • 2. 响应函数
    • 2.1 ref
    • 2.2 reactive
    • 2.3 toRef和toRefs
    • 2.4 readonly
    • 2.5 customRef


1. 组合Api介绍

组合Api其实时用于解决功能、数据和业务逻辑分散的问题,使项目更益于模块化开发以及后期维护。

vue2.x — optionsApi 配置式Api — react类组件

vue3.x — compositionApi 组合Api — react函数组件中hook

setup

  • 它是vue3新增的一个配置项,值为一个函数,所有的组合式 API 方法都写在 setup函数中。
  • 组件中用到的数据,方法 计算属性,事件方法,监听函数,都配置在setup 中。
  • setup的函数值为一个函数,该函数的返回值为一个对象,对象中的属性和方法均可以在模板中直接使用。
  • setup默认情况下不能使用async/await,在读取数据时它只能是json对象,才能读取到里面的属性值,如果你后续使用了异步组件+Suspense组合,可以使用async/await
  • setup中不能使用this
  • setup有两个参数,参数1对应就是props属性对象,但是它不能解构,一但解构响应式就失效,参数2为一个context对象,此对象中有包含attrs, slots, emit,expose。
  • setup选项在组件创建之前执行,一旦props被解析,它就执行了。

2. 响应函数

2.1 ref

ref 的作用是创建一个响应式的数据对象,通过 .value 获取值,主要是对String、Number、Boolean等基本类型的数据响应。

首先来看一下,什么是无法响应的数据:

<template>
  <div>
    <h3>{{ num }}</h3>
    <button @click="addNum">+++</button>
  </div>
</template>

<script>
export default {
  // setup中不能使用this
  // 它必须要有一个返回值,它可以返回 json 对象、函数、async setup()
  // json对象,对象中的属性,可以直接在模板中使用
  // 函数,它就当作是一个组件结构,当前组件不需要 template => render
  // async setup() 当作异步组件 结合 Suspense来使用
  setup() {
    // 定义了一个普通的变量,它不是一个响应式的变量
    let num = 100

    // methods
    const addNum = () => {
      num++
      console.log('setup addNum', num)
    }

    // 此处相当于之前data配置
    return { num, addNum }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

视图中的 num 并没有发生改变。

定义一个响应式的变量:

<template>
  <div>
    <!-- 如果num它是一个ref定义的响应式变量,在模板中调用,你无须写 num.value -->
    <!-- 模板在解析的过程中会给你补上 -->
    <h3>{{ num }}</h3>

    <h1 ref="titleRef">我是一个标题</h1>
    
    <button @click="addNum">+++</button>
  </div>
</template>

<script>
import { ref, shallowRef } from 'vue'
export default {
  // setup中不能使用this
  // 它必须要有一个返回值,它可以返回 json 对象、函数、async setup()
  // json对象,对象中的属性,可以直接在模板中使用
  // 函数,它就当作是一个组件结构,当前组件不需要 template => render
  // async setup() 当作异步组件 结合 Suspense来使用
  setup() {
    // 定义一个响应式的变量
    // 如果ref赋值的为基础类型,是它是用Object.defineProperty来进行响应式处理
    let num = ref(100)
    
    // 绑定到dom元素或自定义组件上
    let titleRef = ref(null)

    // methods
    const addNum = () => {
      // num++
      // 如果你的num它是一个ref定义的响应式变量,则在js中操作它,一定要xx.value来操作
      num.value++

      console.log('setup addNum', num.value)

      console.log(titleRef.value)
    }

    // 此处相当于之前data配置
    return { num, addNum, titleRef }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

对引用类型的响应式处理:

<template>
  <div>
    <div>{{ user1.age }}</div>
    <input type="number" v-model.number="user1.age" />

    <div>{{ user2.age.n }}</div>
    <input type="number" v-model.number="user2.age.n" />
  </div>
</template>

<script>
import { ref, shallowRef } from 'vue'
export default {
  setup() {
    // 如果ref赋值的为引用类型,它是用Proxy来进行响应式处理
    // 引用类型
    let user1 = ref({ id: 1, age: 10 })
    let user2 = ref({ id: 1, age: { n: 100 } })

    // 此处相当于之前data配置
    return { user1, user2 }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

shallowRef:

只处理基本数据类型的响应式, 不进行对象的响应式处理。

<template>
  <div>
    <h3>{{ num.n }}</h3>
    <button @click="addNum">+++</button>
  </div>
</template>

<script>
import { shallowRef } from 'vue'
export default {
  setup() {
    // 只处理基本数据类型的响应式, 不进行对象的响应式处理。
    let num = shallowRef({ n: 200 })
    const addNum = () => {
      // num.value.n++,不再会发生响应式
      // 只能使用下面这种方式进行响应式处理,因为 shallowRef 只能处理基本数据类型
      num.value = { n: num.value.n + 1 }
    }
    return { num, addNum }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

2.2 reactive

如果说 ref 的作用是把一个个数据拆分出来,那么 reactive 的作用就是把数据整合在一起。reactive 的响应式使用 proxy 实现的,它只能处理对象。

深层监听:

<template>
  <div>
    <h3>姓名:{{ state.name }} --- {{ state.age.n }}</h3>
    <input type="number" v-model.number="state.age.n" />
    <button @click="setName">修改姓名</button>
  </div>
</template>

<script>
// ref 把数据拆分出来 id  name age
// reactive 它可以把数据整合在一起,响应式用的就是Proxy,它只能处理对象
import { reactive } from 'vue'
export default {
  setup() {
    // 数据响应式的方式为 Proxy,它参数必须为object  深层监听
    const state = reactive({
      name: '张三',
      age: { n: 22 }
    })
    
    const setName = () => {
      // console.log(state)
      // 修改reative中name属性值 ref-- xxx.value  reactive -- state.xx = xx
      state.name = Date.now() + ''
    }
    return { state, setName }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

浅层监听:

这种情况一般不用,用的更多的是 Ref ,使用 shallowReactive 大多是情况下只是为了性能优化。

<template>
  <div>
    <h3>姓名:{{ state.name }} --- {{ state.age.n }}</h3>
    <input type="number" v-model.number="state.age.n" />
    <button @click="setName">修改姓名</button>
  </div>
</template>

<script>
// ref 把数据拆分出来 id  name age
// reactive 它可以把数据整合在一起,响应式用的就是Proxy,它只能使用对象
import { shallowReactive } from 'vue'
export default {
  setup() {
    // 浅层监听,只监听对象的第1层
    const state = shallowReactive({
      // 姓名会发生变化
      name: '张三',
      // 年龄不会发生变化
      age: { n: 22 }
    })

    const setName = () => {
      state.name = Date.now() + ''
    }

    return { state, setName }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

2.3 toRef和toRefs

在使用 reactive 时,在模板中每次都要写 state. 会让代码变得很繁琐,于是我们可以想到,可不可以在 setup 的返回值中,将 state 结构出来,让模板中减少取数据的层级呢?

<template>
  <div>
    <h3>姓名:{{ name }} --- {{ age.n }}</h3>
    <input type="number" v-model.number="age.n" />
    <button @click="setName">修改姓名</button>
  </div>
</template>

<script>
import { reactive } from 'vue'
export default {
  setup() {
    const state = reactive({
      name: '张三',
      age: { n: 22 }
    })

    const setName = () => {
      state.name = Date.now() + ''

      console.log(state, { ...state })
    }

    // 在setup中reactive引用对象,不能解构,解构它就破坏了响应式
    return { ...state, setName }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

很显然,我们的需求没有实现,在解构 state 后发现,修改姓名并不能响应式的发生改变,但是修改年龄依然可以实现响应式。

从控制台中我们可以发现,state 在解构前是被 proxy 劫持的,而解构后,就变味了普通的 js 对象,不再具有响应式,但是 age 仍然是一个 proxy 对象。

在这里插入图片描述

显然解构并不能实现在模板中减少数据提取的层级,那该怎么办呢?

vue3 为我们提供了 toRef 函数。

toRef:

<template>
  <div>
    <h3>姓名:{{ name }} --- {{ age.n }}</h3>
    <input type="number" v-model.number="age.n" />
    <button @click="setName">修改姓名</button>
  </div>
</template>

<script>
import { reactive,toRef } from 'vue'
export default {
  setup() {
    const state = reactive({
      name: '张三',
      age: { n: 22 }
    })

    const setName = () => {
      state.name = Date.now() + ''

      console.log(toRef(state, 'name'))
    }

    return { age: toRef(state, 'age'), name: toRef(state, 'name'), setName }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

这时候我们可以看到,name 在使用 toRef 后,可以进行响应式,同时在控制台中也可以看到 name 还是一个 peoxy 对象。

toRef 在 setup 的return 中依然需要写很多代码,有没有更简便的写法呢?

vue3 为我们提供了 toRefs。

toRefs:

<template>
  <div>
    <h3>姓名:{{ name }} --- {{ age.n }}</h3>
    <input type="number" v-model.number="age.n" />
    <button @click="setName">修改姓名</button>
  </div>
</template>

<script>
import { reactive,toRefs } from 'vue'
export default {
  setup() {
    const state = reactive({
      name: '张三',
      age: { n: 22 }
    })

    const setName = () => {
      state.name = Date.now() + ''
    }

    return { ...toRefs(state), setName }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

toRef 和 toRefs 需要分场景使用,当我们只需要一两个数据时,用 toRef 比较合适,当需要用到所有数据时 toRefs 更加方便。

2.4 readonly

设置为只读属性。

<template>
  <div>
    <h3>{{ state.name }}</h3>
    <button @click="setName">修改姓名</button>
  </div>
</template>

<script>
// 赋值的数据它是一个只读的,不能修改,只能读取
import { readonly } from 'vue'
export default {
  setup() {
    let state = readonly({ name: '张三' })
    const setName = () => {
      state.name = Date.now() + ''
    }

    return { state, setName }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

2.5 customRef

用于自定义一个 ref。

首先通过 customRef 定义一个具备防抖功能的 ref ,自定义 ref 在工作中通常会封装在 hooks 中。

useDebouncedRef.js:

// 防抖
import { customRef } from 'vue'

const useDebouncedRef = (value, delay = 300) => {
  let timeout
  // track 响应收集,在获取时,收集
  // trigger 响应 在你设置时触发,通知视图更新
  return customRef((track, trigger) => {
    return {
      get() {
        track()
        return value
      },
      set(newValue) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          value = newValue
          trigger()
        }, delay)
      }
    }
  })
}

export default useDebouncedRef

App组件:

<template>
  <div>
    <h3>{{ num }}</h3>
    <input type="number" v-model="num" />
  </div>
</template>

<script>
import useDebouncedRef from './hooks/useDebouncedRef'

export default {
  setup() {
    let num = useDebouncedRef(100)

    return { num }
  }
}
</script>

<style lang="scss" scoped></style>

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32 定时器定时计算

STM32 定时器定时计算STM32 定时器频率例子公式referenceSTM32 定时器频率 定时时间 定时器频率 / 倍频 /装载周期 htim1.Init.Prescaler 72-1;htim1.Init.CounterMode TIM_COUNTERMODE_UP;htim1.Init.Period 1*1000*1000;tim 72x10^6 / (72-1)/ 110001000 1us 根据定时…

RAC/RAC One Node 修改私网/心跳网卡名

cDAS RAC/RAC One Node一般采用ib ip作为私网/心跳ip&#xff0c;有些现场可能会有修改心跳/私网网卡的需求&#xff0c;一般修改网卡也会伴随修改心跳/私网ip的需求。若心跳/私网有高可用&#xff0c;可以一个个修改。 场景1&#xff1a;心跳网卡有高可用 原心跳网卡名 原心…

Vue中 引入使用 localforage 改进本地离线存储(突破5M限制)

1. 简介 说到本地存储数据&#xff0c;首先想到的是 localStorage&#xff0c;应该很多小伙伴都用过&#xff0c;使用很简单。然而&#xff0c;localStorage 却有下面一些缺点&#xff1a; 存储容量限制&#xff0c;大部分浏览器应该最多5M。我就遇到过localStorage存储字符然…

H264码流中SPS PPS详解

1 SPS和PPS从何处而来&#xff1f; 2 SPS和PPS中的每个参数起什么作用&#xff1f; 3 如何解析SDP中包含的H.264的SPS和PPS串&#xff1f; 1 客户端抓包 在做客户端视频解码时&#xff0c;一般都会使用Wireshark抓包工具对接收的H264码流进行分析&#xff0c;如下所示&…

Transform+ASM插桩系列(3)——Transform+ASM的实战

回顾 在上一章讲到创建完buildSrc之后&#xff0c;实现了项目的plugin之后&#xff0c;就可以在plugin注册我们的Transform。这期文章将正式进入重头戏&#xff0c;今天的学习内容有【认识Transform】、【认识AMS】、【插桩实战】 前言 插桩的技巧中&#xff0c;我们要知道 …

Python实现LDA和KNN人脸识别模型(LinearDiscriminantAnalysis和KNeighborsClassifier算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 人脸识别&#xff0c;是基于人的脸部特征信息进行身份识别的一种生物识别技术。用摄像机或摄像头采集含…

【2021-TITS】Deep Learning in Lane Marking Detection: A Survey

概述 回顾了针对路面标线的深度学习算法&#xff0c;主要分析了他们的网络架构及优化目标&#xff1b;此外还总结了现有车道标线相关的数据集&#xff0c;评价基准及常见的数据处理技术 PaperCode 总结 创新点&#xff1a; 1.总结深度学习网络架构、优化目标2.总结了相关现有…

使用Portman、Postman和Newman自动化API测试

几个月前我换了工作和公司&#xff0c;很喜欢这样的变化&#xff0c;但多少会有些不知所措。现在事情已经安排好了一些&#xff0c;我可以回来做一些我喜欢的事情。 现在正在工作的团队是一个新团队&#xff0c;我们正在努力弄清楚我们的流程&#xff0c;并试图尽可能地实现自…

编译原理实验一:源程序的预处理及词法分析程序的设计与实现(python)

实验目的 设计并实现一个包含预处理功能的词法分析程序&#xff0c;加深对编译中词法分析过程的理解。 实验要求 1、实现预处理功能 源程序中可能包含有对程序执行无意义的符号&#xff0c;要求将其剔除。 首先编制一个源程序的输入过程&#xff0c;从键盘、文件或文本框输…

[附源码]java毕业设计校园拓展活动管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

论文阅读之Dynamic Routing Between Capsules(2017)

文章目录前言capsule network参考前言 capsule network 可以简单理解为将神经网络的标量计算&#xff0c;赋予了方向&#xff0c;变换成了向量进行计算。 标量只有大小之分。 向量不仅有大小&#xff0c;还有方向之分。 应该可以略微感受到这种思路的魔力了。 capsule 主要是…

IB历史备考,如何拿高分?

邻近期末考&#xff0c;大伙儿是不是十分焦虑不安呢&#xff1f;大家的老师经常发觉学生们本来知识要点都把握得挺不错的&#xff0c;但每到考試便是拿不上满意的考试成绩&#xff0c;让人十分郁闷&#xff01;因此应对那样的难点&#xff0c;大家的IB历史时间评委为大伙儿筹备…

行业分析| 智慧消防对讲

消防工程关系国计民生&#xff0c;关系到每个公民的人身和财产安全&#xff0c;在每个场所的建设中&#xff0c;消防工程建设是必不可少的一个板块&#xff0c;包括消防应急通道建设和应急设备建设两个方面。其中消防系统设备建设主要分为九大系统的建设&#xff1a;消防水系统…

VectorCAST测试工具环境搭建

**目的&#xff1a;**本文提供VectorCAST使用的实际操作方法&#xff0c;以便项目可以很好的使用VectorCAST工具。 适用范围&#xff1a;VectorCAST是一个专门针对嵌入式软件的C/C代码进行单元测试的工具&#xff0c;它可以自动生成测试用例、评估测试结果并生成测试报告。 **工…

十年来高薪专业变成了它——信息安全

“什么专业好就业&#xff1f;” “什么专业以后赚的钱多&#xff1f;” 确实&#xff0c;专业对应的行业薪资各有不同&#xff0c;选对了专业赢在起跑线也不是没有可能&#xff01; 麦可思机构分析了近十年大学生就业数据情况&#xff0c;发现从2011年到2020年的大学毕业生高…

Windows简单安装redis

1.去git下载 或者去搜点资源&#xff0c;windows下载是压缩包&#xff0c;找个目录解压进去。 Github下载地址&#xff1a;https://github.com/MicrosoftArchive/redis/releases 2.打开cmd 尝试启动 比如我放在d盘soft下面&#xff0c;windows你直接打开cmd&#xff0c;输入d…

Baklib知识分享|文档生命周期:确保您的文档产出效率

一个多世纪以来&#xff0c;文档一直是任何产品或服务的支柱。它是用户在使用您的产品、应用程序、网站或其他软件服务时所引用的内容。但在现代&#xff0c;随着大多数帮助或支持文档从传统形式转移到数字形式&#xff0c;对效率的需求比以往任何时候都更加明显。此外&#xf…

[附源码]SSM计算机毕业设计基于javaweb电影购票系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【Shell 脚本速成】01、编程语言与 Shell 脚本介绍

目录 一、编程语言介绍 二、shell介绍 1、shell介绍 2、bash shell基本特性 2.1 命令和文件自动补全 2.2 常见的快捷键 3、shell脚本介绍 准确来说&#xff1a; 3.1 案例演示 3.2 什么时候用到脚本&#xff1f; 4、shell脚本语法 4.1 shell脚本组成 4.2 脚本文件命…

Spring事务配置(案例:转账业务追加日志,事务传播行为)

目录 Spring事务配置 案例 事务传播行为 代码实现&#xff1a; 1.文件大致格式&#xff1a; 2.ServiceAdvise&#xff08;AOP功能包&#xff09; 3.JdbcConfig&#xff08;jdbc配置文件&#xff0c;包含了事务管理器&#xff09; 4.MybatisConfig&#xff08;mybatis配置…