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

这篇具有很好参考价值的文章主要介绍了【vue3】11-Vue 3中的Composition Api(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

options Api的弊端

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

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

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

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

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

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

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

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

这就是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】11-Vue 3中的Composition Api(一)

这个时候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情况:

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

常见使用ref情况:

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


setup中的其他函数(了解)

1. readonly函数

先来看下边的代码:

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

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

如上述代码所示:

我们通过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 的错误示例:文章来源地址https://www.toymoban.com/news/detail-480493.html

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

到了这里,关于【vue3】11-Vue 3中的Composition Api(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从Vue2到Vue3【二】——Composition API(第二章)

    内容 链接 从Vue2到Vue3【零】 Vue3简介 从Vue2到Vue3【一】 Composition API(第一章) 从Vue2到Vue3【二】 Composition API(第二章) 从Vue2到Vue3【三】 Composition API(第三章) 从Vue2到Vue3【四】 Composition API(第四章) Vue3作为Vue.js框架的最新版本,引入了许多令人激动的新特性和改进。其

    2024年02月17日
    浏览(30)
  • 从Vue2到Vue3【三】——Composition API(第三章)

    内容 链接 从Vue2到Vue3【零】 Vue3简介 从Vue2到Vue3【一】 Composition API(第一章) 从Vue2到Vue3【二】 Composition API(第二章) 从Vue2到Vue3【三】 Composition API(第三章) 从Vue2到Vue3【四】 Composition API(第四章) 随着Vue 3的发布,我们迎来了一套强大且令人兴奋的 组合式API ,这为开

    2024年02月16日
    浏览(27)
  • 从Vue2到Vue3【四】——Composition API(第四章)

    内容 链接 从Vue2到Vue3【零】 Vue3简介 从Vue2到Vue3【一】 Composition API(第一章) 从Vue2到Vue3【二】 Composition API(第二章) 从Vue2到Vue3【三】 Composition API(第三章) 从Vue2到Vue3【四】 Composition API(第四章) 从Vue2到Vue3【五】 从Vue2到Vue3【五】——新的组件(Fragment、Teleport、S

    2024年02月16日
    浏览(29)
  • Composition API 的优势、新的组件(Fragment,Teleport,Suspense)【Vue3】

    使用传统OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改。 我们可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起。 在Vue2中:组件必须有一个根标签 在Vue3中:组件可以没有根标签,内部会将多个标签包含在一个

    2024年02月02日
    浏览(34)
  • Vue3的手脚架使用和组件父子间通信-插槽(Options API)学习笔记

    全局安装最新vue3 升级Vue CLI: 如果是比较旧的版本,可以通过下面命令来升级 通过脚手架创建项目 父组件 子组件 UserComponent.vue 父组件 **子组件1 JiaComponent.vue ** ** 子组件2 JianComponent.vue ** 父组件 子组件 TitleComponents.vue 父组件 **子组件 NavComponent.vue ** 父组件 子组件 NavCompone

    2024年02月05日
    浏览(33)
  • Vue 3 Composition API 详解

    在Vue 3中,引入了一个新的Composition API,旨在提供一种更灵活和可重用的方式来组织组件代码。Composition API基于函数式编程思想,允许开发者将逻辑和状态管理逻辑分离,使代码更加清晰和可维护。 响应式数据 在Vue 3中,响应式数据是组件状态的重要组成部分。通过使用 re

    2024年01月21日
    浏览(30)
  • 详解Vue 3 的 Composition API

    Vue 3 的 Composition API 是一种新的组合式 API 风格,它可以更好地组织和复用组件逻辑。相比于 Vue 2 的 Options API,Composition API 提供了更灵活和可组合的方式来编写组件。 下面是 Composition API 的一些特点和优势: 函数式组件:Composition API 支持使用函数式组件的方式来编写组件。

    2024年02月10日
    浏览(27)
  • vue/composition-api 的使用

    最近我们项目是 vue2,但是要使用 jsx + composition ,所以来学习一下这个 vue/composition-api (一)安装 (二)注册 在 main.ts 中 (三)使用 最基本的组件: defineComponent 本身的功能很简单,但是最主要的功能是为了 ts 下的类型推导~ 1. setup 函数 setup 在 create 实例在初始化之前调

    2024年02月05日
    浏览(32)
  • Vue Composition API之侦听器watch/watchEffect

    在日常的开发中,很多时候我们需要去对一些状态进行监听,比如当显示学生的成绩列表时,我们使用一个学生的学号student_num作为请求成绩的参数,如果没有监听机制,当学号student_num改变时,我们需要依赖用户的操作去刷新成绩。但是有了侦听器,我们可以通过侦听器去监

    2024年02月08日
    浏览(29)
  • 【Vue3】vue3中的watchEffect使用及其他的API

    目录  一,watchEffect 二,生命周期 三,什么是hooks? 四,toRef  五,其他组合式API 5.1shallowReactiveshallowRef 5.2readonlyshallowReadonly 5.3.toRawmarkRaw 5.4自定义Ref-customRef ​5.5provide$inject 5.6响应式数据的判断 写在最后     1.watch: 既要指明监视的属性,也要指明监视的回调。 2.watchEffect: 不

    2024年02月01日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包