【vue3】11-Vue 3中的Composition Api(一)

news2024/11/25 0:28:56

Vue3 - composition Api

  • 前言
    • options Api的弊端
  • 认识composition Api
    • Set up函数的基本使用
      • set up函数的参数
      • set up函数的返回值
    • Set up中数据的响应式
      • 1. Reactive API
      • 2. Ref API
      • 3. ref和reactive的开发
    • setup中的其他函数(了解)
    • setup中禁用this

前言

options Api的弊端

在Vue2中,我们编写组件的方式是Options APl:

  • Options API的一大特点就是在对应的属性中编写对应的功能模块;
  • 比如data定义数据methods中定义方法computed中定义计算属性watch中监听属性改变,也包括生命周期钩子;

但是这种代码有一个很大的弊端:

  • 当我们实现某一个功能时,这个功能对应的代码逻辑会被拆分到各个属性中;
  • 当我们组件变得更大、更复杂时,逻辑关注点的列表就会增长,那么同一个功能的逻辑就会被拆分的很分散;
  • 尤其对于那些一开始没有编写这些组件的人来说,这个组件的代码是难以阅读和理解的(阅读组件的其他人);

下面我们来看一个非常大的组件,其中的逻辑功能按照颜色进行了划分:

  • 这种碎片化的代码使用理解和维护这个复杂的组件变得异常困难,并且隐藏了潜在的逻辑问题;
  • 并且当我们处理单个逻辑关注点时,需要不断的跳到相应的代码块中;

在这里插入图片描述

如果我们能将同一个逻辑关注点相关的代码收集在一起会更好。

这就是Composition API想要做的事情,以及可以帮助我们完成的事情。


认识composition Api

那么既然知道Composition API想要帮助我们做什么事情,接下来看一下到底是怎么做呢?

  • 为了开始使用Composition API,我们需要有一个可以实际使用它(编写代码)的地方;
  • 在Vue组件中,这个位置就是setup函数;

setup其实就是组件的另外一个选项:

  • 只不过这个选项强大到我们可以用它来替代之前所编写的大部分其他选项;
  • 比如methods、computed、watch、data、生命周期等等;

接下来我们一起学习这个函数的使用:

  • 函数的参数
  • 函数的返回值

Set up函数的基本使用

set up函数的参数

我们先来研究一个setup函数的参数,它主要有两个参数:

  • 第一个参数:props
  • 第二个参数:context

props非常好理解,它其实就是父组件传递过来的属性会被放到props对象中,我们在setup中如果需要使用,那么就可以直接通过props参数获取:

  • 对于定义props的类型,我们还是和之前的规则是一样的,在props选项中定义;
  • 并且在template中依然是可以正常去使用props中的属性,比如message;
  • 如果我们在setup函数中想要使用props,那么不可以通过this去获取(后面我会讲到为什么);
  • 因为props有直接作为参数传递到setup函数中,所以我们可以直接通过参数来使用即可;

另外一个参数是context,我们也称之为是一个SetupContext,它里面包含三个属性:

  • attrs:所有的非prop的attribute;
  • slots:父组件传递过来的插槽(这个在以渲染函数返回时会有作用,后面会讲到);
  • emit:当我们组件内部需要发出事件时会用到emit(因为我们不能访问this,所以不可以通过 this.$emit发出事件);

set up函数的返回值

setup既然是一个函数,那么它也可以有返回值,它的返回值用来做什么呢?

  • setup的返回值可以在模板template中被使用;
  • 也就是说我们可以通过setup的返回值来替代data选项;

甚至是我们可以返回一个执行函数代替在methods中定义的方法:

  • 下面通过从一个计数器案例来体验下:
<template>
  <div class="app">
    <h2>当前计数: {{ counter }}</h2>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>

<script>

  export default {
    // 使用setup函数
    setup() {
	  //1.定义counter的内容
	  // 默认定义的数据都不是响应式数据
      let counter = 100
      // setup函数定义函数(方法)
      const increment = () => {
        counter++
      }
      // setup函数定义函数(方法)
      const decrement = () => {
        counter--
      }

      // 外部要使用的数据需要通过return导出
      return {
        counter,
        increment,
        decrement
      }
    }
  }
</script>

运行上述代码,发现点击 increment 或者 decrement按钮进行操作时,发现counter展示的数值没有发生变化:

因为默认定义的数据不是响应式数据,即对于一个定义的变量来说,默认情况下,Vue并不会跟踪它的变化,来引起界面的响应式操作;

Set up中数据的响应式

如果想为在setup中定义的数据提供响应式的特性,那么我们有如下两种常见的方案:

1. Reactive API

如果想为在setup中定义的数据提供响应式的特性,那么我们可以使用reactive的函数:

<template>
    <div class="app">
        <h2>message:{{ message }}</h2>
        <button @click="changeMessage">修改message</button>
    </div>
    <hr>
    <h2>账号:{{ account.username }}</h2>
    <h2>密码:{{ account.password }}</h2>
    <button @click="changeAccount">修改账户名</button>
    <hr>
</template>
  
<script>
import { reactive, ref } from "vue";

export default {
    setup() {
        // 1.定义普通的数据
        // 缺点:数据不是响应的
        let message = "hello world";
        function changeMessage() {
            message = "message已被修改"//不生效
            console.log(222);//222
        }

        // 2.定义响应式的数据
        // 2.1 reactive函数:定义复杂类型的数据(不常用)
        const account = reactive({
            username: "wxx",
            password: "1212135"
        })

        function changeAccount() {
            account.username = "飒飒"//生效
        }

        return {
            message,
            changeMessage,
            account,
            changeAccount,
        }
    }
}
</script>

那么这是什么原因呢?为什么就可以变成响应式的呢?

  • 这是因为当我们使用reactive函数处理我们的数据之后,数据再次被使用时就会进行依赖收集;
  • 数据发生改变时,所有收集到的依赖都是进行对应的响应式操作(比如更新界面);
  • 事实上,我们编写的data选项,也是在内部交给了reactive函数将其编程响应式对象的;

2. Ref API

reactive API对传入的类型是有限制的,它要求我们必须传入的是一个对象或者数组类型:

  • 如果我们传入一个基本数据类型(String、Number、Boolean)会报一个警告;

在这里插入图片描述

这个时候Vue3给我们提供了另外一个APl: ref API

  • ref 会返回一个可变的响应式对象,该对象作为一个 响应式的引用 维护着它内部的值,这就是ref名称的来源;
  • 它内部的值是在ref的 value属性中被维护的;

使用示例:

<template>
    <!-- 默认情况下载template中使用ref时,vue会自动对其进行解包(取出其中value) -->
    <h2>当前计数:{{ counter }}</h2>
    <button @click="increment">+1</button>
</template>
  
<script>
import { ref } from "vue";

export default {
    setup() {
        // 2.2 Ref函数:定义简单类型的数据(也可以定义复杂类型数据)
        //错误写法: const counter = ref(0);也能实现变动,因为修改的是counter的value值不少修改的counter本身
        let counter = ref(0)

        function increment() {
            // 错误写法:counter++
            counter.value++
        }

        return {
            counter,
            increment
        }
    }
}
</script>

这里有两个注意事项:

  • 模板中引入ref的值时,Vue会自动帮助我们进行解包操作,所以我们并不需要在模板中通过ref.value的方式来使用;
  • 但是在setup函数内部,它依然是一个ref引用,所以对其进行操作时,我们依然需要使用ref.value的方式;

3. ref和reactive的开发

  • 常见使用reactive情况:

在这里插入图片描述

常见使用ref情况:

在这里插入图片描述


setup中的其他函数(了解)

1. readonly函数

先来看下边的代码:

  • 在下面的示例中,通过props接收到了父组件传递过来的数据后,直接在当前组件进行了修改,这样是违背了单向数据流

在这里插入图片描述

如上述代码所示:

我们通过reactive或者ref可以获取到一个响应式的对象,但是某些情况下,我们传入给其他地方(组件)的这个响应式对象希望在另外一个地方(组件)被使用,但是不能被修改,这个时候如何防止这种情况的出现呢?

  • Vue3为我们提供了readonly的方法;
  • readonly会返回原始对象的只读代理〈也就是它依然是一个Proxy,这是一个proxy的set方法被劫持,并且不能对其进行修改);

在开发中常见的readonly方法会传入三个类型的参数:

  • 类型一:普通对象;
  • 类型二: reactive返回的对象;
  • 类型三:ref的对象;

在readonly的使用过程中,有如下规则:

readonly返回的对象都是不允许修改的, 但是经过readonly处理的原来的对象是允许被修改的;

  • 比如 const info = readonly(obj),info对象是不允许被修改的;
  • 但是可以通过修改obj来修改info, obj被修改时,readonly返回的info对象也会被修改;
  • 但是我们不能去修改readonly返回的对象info;
setup() {
	const info = reactive({
	  name: "chenyq",
	  age: 18,
	  height: 1.88
	})
  
	// 为info包裹一个readonly, 子组件就无法修改
	const newInfo = readonly(info)
	console.log(newInfo)

	return {
	  info,
	  changeInfo,
	  newInfo
	}
}

2. Reactive判断的API(了解)

isProxy

检查对象`是否是由reactive或 readonly创建的proxy。

isReactive

检查对象是否是由reactive创建的响应式代理:
如果该代理是readonly创建的,但包裹了由reactive创建的另一个代理,它也会返回true;

isReadonly

检查对象是否是由readonly 创建的只读代理。

toRaw

返回reactive或 readonly代理的原始对象(不建议保留对原始对象的持久引用。请谨慎使用)。

shallowReactive

创建一个响应式代理,它跟踪其自身property 的响应性,但不执行嵌套对象的深层响应式转换(深层还是原生对象)。

shallowReadonly

创建一个proxy,使其自身的property为只读,但不执行嵌套对象的深度只读转换(深层还是可读 可写的)。

3. toRef(s)函数

如果我们希望在模板中展示name,age等数据的值不是info.name,info.age这样的形式,而是直接使用所有对其解构,如下代码示例:

setup() {
  const info = reactive({
    name: "sevgilid",
    age: 19,
    height: 1.87
  })

  const { name, age, height } = info
}

我们会发现直接解构后无论是修改解构后的变量,还是修改reactive返回的state对象,数据都不再是响应式的:

那么如何让解构出来的属性变成响应式的呢?这就需要使用到toRefstoRef函数:

  • toRefs 函数可以将一个响应式对象转换为一个基本类型的对象,并且对象中每个属性都是一个单独的源,并且可以进行解构和响应性访问
  • toRef 函数可以将一个响应式对象中的 指定属性 转换为一个新的响应式数据,这个新的数据可以独立地更新,并且对原响应式对象不会造成影响;
    • 这个函数接收对象键名称两个参数,返回一个带有 value 属性的 ref 对象\

代码示例:

<template>
    <div class="app">
        <!-- <h2>info:{{ info.name }}-{{ info.age }}</h2> -->
        <h2>info:{{ name }}-{{ age }}-{{ height }}</h2>
        <button @click="age++">修改age</button>
    </div>
</template>
   
<script>

import { reactive, toRefs, toRef } from 'vue';
export default {
    setup() {
        const info = reactive({
            name: "sevgilid",
            age: 18,
            height: 1.88

        })
        // reactive被解构后会变成普通的值,失去响应式
        // 使用toRefs,toRef方法就可以
        const { name, age } = toRefs(info)
        // 单独对一个结构
        const height = toRef(info, "height")

        return {
            name,
            age,
            height
        }
    }
}

setup中禁用this

Vue 3 中的 setup 函数是一个新的组件选项。它允许我们在组件渲染之前执行一些前置操作,比如数据处理、事件绑定等;

与 Vue 2.x 中的 data、computed、methods 等属性不同,setup 函数只接收 props 作为参数,并且不能访问 this

为什么不能使用this:

  • 在 Vue 3 中,模板编译的过程发生了很大的变化,这就导致了 this 不能再指向 Vue 实例对象;
  • 在 Vue 2.x 中,我们可以通过 this.$xxx 访问全局实例,但是在 Vue 3 中,由于模板编译的变化,我们需要使用 provide 和 inject 手动注入/引用全局实例对象,而不能再通过 this 来访问它们。

下面的代码演示了 setup 函数内使用 this 的错误示例:

export default {
  setup() {
    console.log(this.$route) // 无法访问 this
  }
}

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

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

相关文章

Ansible自动化运维工具的初步了解及模块使用

1.Ansible的相关知识 1.1 Ansible工具的了解 Ansible是一个基于Python开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pubbet和Saltstack能实现的功能&#xff0c;Ansible基本上都可以实现。Ansible能…

tp6安装并使用rabbitMQ

最近因为业务需要,要用到MQ就去研究了一下,说实话,安装环境给我搞自闭了,大概是我太菜 刚开始使用yum换源,各种安装卸载始终找不到自己要用的版本,后来全部卸载,下载安装包 编译安装解百忧 我用的是erlang 25.3 的版本,MQ使用的是3.11.3的版本,符合官方要求,这里的版本是有强…

智能果树叶部疾病识别实践,基于HOG+SVM和轻量级的CNN模型分别开发构建苹果果树叶部疾病识别分析系统

在农业领域中&#xff0c;将机器学习和深度学习模型结合应用有着广泛的实用意义&#xff0c;在这块相关的实践中以往的项目开发实践则是主要集中在农作物种植相关的&#xff0c;今天本文的主要目的就是开发构建果树叶部疾病识别分析系统&#xff0c;这里是以苹果果树叶部疾病数…

springcloud环境搭建

目录 1、创建一个父项目 ​编辑 2、创建子项目 2.1创建订单系统-order ​编辑 2.2创建库存系统-stock 3、创建rest服务 3.1添加web依赖 3.2编写controller 3.3订单中需要调用库存中的扣减库存的接口 通过idea开发工具进行搭建 1、创建一个父项目 通过spring initializr…

Django基础入门:后台管理 超级用户 数据表注册操作③

Django基础入门&#xff1a;后台管理 超级用户 数据表注册操作③ Django Admin数据表后台管理超级用户数据表注册admin操作日志 &#x1f3d8;️&#x1f3d8;️个人简介&#xff1a;以山河作礼。 &#x1f396;️&#x1f396;️:Python领域新星创作者&#xff0c;CSDN实力新星…

使用randoop自动化生成测试用例

1. 综述 使用randoop自动化生成测试用例 2. 操作 下载randoop的jar包&#xff1b;将jar包和所要测试的类&#xff08;如Calculate.class&#xff09;放在同一个文件夹&#xff1b;在此文件夹打开命令行提示符&#xff0c;输入如下命令&#xff1a; java -ea -classpath .;ra…

嵌入式Linux驱动开发 05:阻塞与非阻塞

文章目录 目的基础说明开发准备驱动程序应用程序 O_NONBLOCK应用程序驱动程序程序演示 poll应用程序驱动程序程序演示 异步通知应用程序驱动程序程序演示 总结 目的 不管在应用开发还是驱动开发中阻塞和非阻塞都是绕不开的话题。这篇文章将介绍相关的基础内容。 这篇文章中内…

Redis命令-认识NoSQl和Redis常见的通用命令

1. 认识NoSQL 非关系型数据库 NoSQL是指一类非关系型数据库&#xff0c;它们采用的数据模型不同于传统的关系模型&#xff0c;它通常使用键值对、文档、图形等非传统的数据结构进行数据存储&#xff0c;不遵循预定义的模式和模型。NoSQL数据库通常分布式、高可扩展性&#xff0…

理解Java ThreadLocal

原文链接 理解Java ThreadLocal ThreadLocal是Java提供的为每个线程存储线程独立的数据的存储方式&#xff0c;也就是说用ThreadLocal来保存的数据&#xff0c;只能被当前线程所访问&#xff0c;其他线程无法访问&#xff0c;因为只有&#xff08;一个线程&#xff09;当前线程…

六级备考6天|CET-6|听力第五六讲|6月11日|19:44~20:07

目录 第五讲 第六讲 第五讲 第六讲 ​​​​​​​

支付宝认证的作用是什么?考试方向有哪些?

通过考证书来提升自己的能力&#xff0c;是现在的打工人经常会做的事&#xff0c;而对于从事信息通信技术行业的人来说&#xff0c;可以选择的证书非常多&#xff0c;其中支付宝认证是一个新设立的证书&#xff0c;但是实用性非常高。支付宝作为我们生活中常用的软件&#xff0…

arthas 的初使用

Arthas 是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对业务问题进行诊断&#xff0c;包括查看方法调用的出入参、异常&#xff0c;监测方法执行耗时&#xff0c;类加载信…

PD QC诱骗取电应用IC《乐得瑞LDR6328S》广泛应用于各大小家电

随着现在智能家居的应用越来越广泛&#xff0c;带电池的产品一天比一天多&#xff0c;今天这篇文章就来讲一下那些支持快速充电(PD QC)的产品应用电路是怎么实现的 USB PD受电端取电芯片&#xff08;乐得瑞取电受电)LDR6328S 支持多协议快充取电&#xff01; 1、概述 LDR6328S…

推荐5款你可能没见过的效率软件

你有没有想过&#xff0c;有些软件能让你的电脑用起来更方便&#xff0c;更快&#xff0c;更好看&#xff1f;这篇文章就为你介绍了五款这样的软件&#xff0c;它们分别是BreeZip&#xff0c;ClipClip&#xff0c;燃精灵&#xff0c;Sticky Notes和Tabby。下面我们来看看它们都…

增强 Kubernetes 可观测性:API Server Tracing 特性已到达 Beta 版本

标题 在分布式系统中&#xff0c;很难弄清楚问题在哪里。 想象一个场景&#xff0c;这也是 Kubernetes 集群管理员最常遇到的问题&#xff0c;Pod 无法正常启动&#xff0c;这时候作为管理员&#xff0c;我们会先去思考这可能是哪个组件出了问题&#xff0c;然后去对应的组件查…

Parallel Desktop下的Centos 9 ping通网络,配置静态ip的全过程

目录 一、发现问题1. 找不到网卡配置文件2. 网络重启的命令一直无法执行成功 二、分析问题三、解决问题系统环境1. 打开网卡配置文件2. 修改ipv4配置3. 重载网卡配置文件4. ping通&#xff0c;可以正常上网了 四、疑问1. 如何确定自己是不是设置了静态ip2. DHCP是固定静态ip 的…

OC(iOS)中常见的面试题汇整(大全)

你如何理解OC这门语言的?谈一下你对OC的理解? OC语言是C语言的一个超集,只是在C语言的基础上加上了面向对象的语言特征,如:继承,封装,多态. 封装:把属性和方法封装成一个类,方便我们使用 多态:不同对象对于同一消息的不同响应,子类可以重写父类的方法,且…

SpringMVC简介及入门案例

1.SpringMVC简介 SpringMVC是一种基于Java实现MVC模型的轻量级Web框架优点&#xff1a;相较于Servlet使用简单&#xff0c;开发便捷。灵活性比较强。 后端做表现层技术开发的框架有Servlet&#xff0c;SpringMVC技术同样也是做表现层技术开发框架&#xff0c;JDBC以及Mybatis数…

Linux内核中内存管理相关配置项的详细解析6

接前一篇文章&#xff1a;Linux内核中内存管理相关配置项的详细解析5 六、Memory hotplug 此项只有选中和不选中两种状态&#xff0c;默认为选中。 此项展开后如下图所示&#xff1a; 1. Online the newly added memory blocks by default 对应配置变量为&#xff1a;CONFIG…