Vue3 之 Composition API

Vue3 之 Composition API_第1张图片

目录

一、基本概念

1. Options API

2. Composition API

二、setup函数

1. setup函数的参数

props

context

栗子

        父组件

        子组件 

2. setup函数的返回值

代码

效果

三、定义响应式数据的两种方式

1. Reactive API

01 - 栗子

        代码

        效果 

02 - Reactive判断的API 

2. Ref API ( 常用 )

01 - 基本使用

        代码

        效果 

02 - Ref自动解包

        注意事项

03 - Ref判断的API

04 - 自定义Ref => customRef

        新建customDebounceRef.js文件

        使用

        效果 

四、readonly

1. 概念

2. 使用

五、toRefs && toRef

1. toRefs

代码

效果 

2. toRef 

六、computed

方式一

方式二

01 - 代码 

02 - 效果 

七、setup中使用ref获取元素或组件

1. 获取元素

2. 获取组件

01 - 子组件 

02 - 父组件

八、生命周期函数

九、provide && inject

1. 父组件代码

2. 子组件代码

3. 效果

十、 侦听数据的变化之watch

1. 侦听单个数据源

01 - 监听具体的某个值

02 - 传入响应式对象

        ref对象

        reactive对象 

2. 侦听多个数据源

01 - 代码

02 - 效果

3. watch的选项

代码

十一、侦听数据的变化之watchEffect

1. watchEffect的基本使用

01 - 代码

02 - 效果 

2. watchEffect的停止监听

01 - 代码

02 - 效果 

3. watchEffect清除副作用

01 - 什么是清除副作用

02 - 如何使用

03 - 代码

04 - 效果 

4. watchEffect的执行时机

代码

5. 和watch的区别

十二、自定义指令

1. 自定义指令的简单使用

01 - 默认实现方式

02 - 局部指令

03 - 全局指令

04 - 效果

2. 指令的生命周期

01 - Vue3

02 - Vue2 与 Vue3对比

3. 指令的参数和修饰符 

4. 时间显示栗子

01 - 代码

02 - 效果

十三、script setup语法糖

1. 概念

2. 顶层的绑定会被暴露给模板

3. 导入的组件直接使用

4. defineProps()

01 - 父组件

02 - 子组件

5. defineEmits()

01 - 子组件

02 - 父组件

6. defineExpose()

01 - 子组件

02 - 父组件 


一、基本概念

1. Options API

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

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

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

2. Composition API

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

setup函数 : 
  • setup其实就是组件的另外一个选项
  • 只不过这个选项强大到我们可以用它来替代之前所编写的大部分其他选项
  • 比如methods、computed、watch、data、生命周期等等

二、setup函数

1. setup函数的参数

setup函数有两个主要的参数 : props 、context

props

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

  • 对于定义props的类型,还是和Vue2的规则是一样的,在props选项中定义
  • 并且在template中依然是可以正常去使用props中的属性
  • 如果在setup函数中想要使用props,那么不可以通过 this 去获取 ( 没有this )
    • 内部调用setup函数的时候是直接调用的,没有绑定this,所以没有
    • props有直接作为参数传递到setup函数中,所以可以直接通过参数来使用即可

context

context,也称之为是一个SetupContext,它里面包含三个属性

  • attrs:所有的非prop的attribute ( 传了属性过来,但是没用props接受的,会在这里 )
  • slots:父组件传递过来的插槽(这个在以渲染函数返回时会有作用)
  • emit:当我们组件内部需要发出事件时会用到emit

栗子

        父组件




        子组件 




2. setup函数的返回值

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

最后导出的一定要是个对象

代码




效果

Vue3 之 Composition API_第2张图片

因为只是定义了个变量,然后导出了,并没有使它响应式

三、定义响应式数据的两种方式

1. Reactive API

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

ps : 如果传入一个基本数据类型(String、Number、Boolean)会报一个警告

 

应用场景 : reactive API对传入的类型是有限制的,它要求我们必须传入的是一个对象或者数组类型,最好相互有关联的数据时使用

reactive : 

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

01 - 栗子

        代码




        效果 

Vue3 之 Composition API_第3张图片

02 - Reactive判断的API 

  • isProxy : 检查对象是否是由 reactive 或 readonly创建的 proxy
  • isReactive : 检查对象是否是由 reactive创建的响应式代理,如果该代理是 readonly 建的,但包裹了由 reactive 创建的另一个代理,它也会返回 true
  • isReadonly : 检查对象是否是由 readonly 创建的只读代理
  • toRaw : 返回 reactive 或 readonly 代理的原始对象建议保留对原始对象的持久引用。请谨慎使用)
  • shallowReactive : 建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (深层还是原生对象),只响应第一层
  • shallowReadonly : 创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换(深层还是可读、可写的)只检查第一层

2. Ref API ( 常用 )

Ref函数 : 定义简单类型的数据,也可以定义复杂类型的数据

 

应用场景 : 定义一些简单的数据,或者从接口中获得的数据

Ref : 

  • ref 会返回一个可变的响应式对象,该对象作为一个 响应式的引用 维护着它内部的值,这就是ref名称的来源
  • 它内部的值是在ref的 value 属性中被维护的
  • 不管传入的是基本类型还是引用类型,都放在.value中

使用的时候是用 .value,但是有两个注意事项

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

01 - 基本使用

        代码




        效果 

Vue3 之 Composition API_第4张图片

02 - Ref自动解包

就是不用在template中使用.value

        注意事项

1. 模板中的解包是浅层的解包,如果放到了对象中,则接包不了

2. 如果把ref返回的对象又放入到reactive中,那么也会自动解包

03 - Ref判断的API

  • isRef : 判断值是否是一个ref对象
  • unref : 如果我们想要获取一个ref引用中的value,那么也可以通过unref方法
    • 如果参数是一个 ref,则返回内部值否则返回参数本身
    • 这是 val = isRef(val) ? val.value : val 的语法糖函数
  • shallowRef : 创建一个浅层的ref对象
  • triggerRef : 手动触发和 shallowRef 相关联的副作用

Vue3 之 Composition API_第5张图片

04 - 自定义Ref => customRef

创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显示控制
  • 它需要一个工厂函数,该函数接受 track 和 trigger 函数作为参数
  • 并且应该返回一个带有 get 和 set 的对象
  • 简单写一个带防抖的ref 

        新建customDebounceRef.js文件

// 导入customRef
import { customRef } from 'vue';

export default function (value) {
  let timer = null;
  // track收集依赖    trigger更新数据
  return customRef((track, trigger) => {
    return {
      get() {
        // 先收集依赖
        track();
        // 把数据返回
        return value;
      },
      set(newValue) {
        // 防抖
        clearTimeout(timer);
        timer = setTimeout(() => {
          // 设置数据
          value = newValue;
          // 更新数据
          trigger();
        }, 1000);
      }
    };
  });
}

        使用





        效果 

 Vue3 之 Composition API_第6张图片

四、readonly

1. 概念

通过reactive或者ref可以获取到一个响应式的对象,但是某些情况下,传入给其他地方(组件)的这个 响应式对象希望在另外一个地方(组件)被使用

但是不能被修改 

  • readonly的方法
  • readonly会返回原始对象的只读代理(也就是它依然是一个Proxy,这是一个proxy的set方法被劫持,并且不能对其进行修改)
在开发中常见的readonly方法会传入三个类型的参数:
  • 类型一:普通对象
  • 类型二:reactive返回的对象
  • 类型三:ref的对象

2. 使用

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

  • readonly返回的对象都是不允许修改
  • 但是经过readonly处理的原来的对象是允许被修改的
    • 比如 const info = readonly(obj),info对象是不允许被修改的
    • obj被修改时,readonly返回的info对象也会被修改
    • 但是不能去修改readonly返回的对象info

本质上就是readonly返回的对象的setter方法被劫持了

Vue3 之 Composition API_第7张图片

五、toRefs && toRef

1. toRefs

如果使用ES6的解构语法,对reactive返回的对象进行解构获取值,那么之后无论是修改结构后的变量,还是修改reactive 返回的state对象数据都不再是响应式

Vue3 之 Composition API_第8张图片

如何改成响应式呢,Vue提供了一个toRefs的函数

可以将reactive返回的对象中的属性都转成ref,这样解构出来的就是响应式的了

代码




效果 

Vue3 之 Composition API_第9张图片

2. toRef 

如果只希望转换reactive对象中的其中某个属性为ref, 那么可以使用toRef的方法

 

ps : 这个效率会更高点

Vue3 之 Composition API_第10张图片

六、computed

Vue2

使用的是computed属性

Vue3

需要在setup函数中使用computed方法来编写一个计算属性

方式一

接收一个getter函数,并为 getter 函数返回的值,返回一个不变的 ref 对象



方式二

接收一个具有 get 和 set 的对象,返回一个可变的(可读写)ref 对象

01 - 代码 



02 - 效果 

Vue3 之 Composition API_第11张图片

七、setup中使用ref获取元素或组件

要定义一个ref对象,绑定到元素或者组件的ref属性上即可

1. 获取元素



2. 获取组件

01 - 子组件 




02 - 父组件



八、生命周期函数

setup中可以直接使用导入的onX函数注册生命周期,并且同一个生命周期可以使用多次

 

ps : 之前在created和beforeCreated生命周期中编写的代码,直接在setup函数中编写即可

Vue3 之 Composition API_第12张图片

九、provide && inject

provide可以传入两个参数 : 

  • name:提供的属性名称
  • value:提供的属性值

inject可以传入两个参数 : 

  • 对应provide传过来的name值
  • 默认值

1. 父组件代码






2. 子组件代码





3. 效果

Vue3 之 Composition API_第13张图片

十、 侦听数据的变化之watch

watch : 

  • watch需要侦听特定的数据源,并在回调函数中执行副作用
  • 默认情况下它是惰性的,只有当被侦听的源发生变化时才会执行回调
  • 与watchEffect的比较,watch允许我们懒执行副作用(第一次不会直接执行)
  • 更具体的说明当哪些状态发生变化时,触发侦听器的执行
  • 访问侦听状态变化前后的值

1. 侦听单个数据源

watch侦听函数的数据源有两种类型:

  • 一个getter函数:但是该getter函数必须引用可响应式的对象(比如reactive或者ref)
  • 直接写入一个可响应式的对象,reactive或者ref(比较常用的是ref)

01 - 监听具体的某个值

用来监听ref 或者 reactive对象中的具体属性可使用

Vue3 之 Composition API_第14张图片

02 - 传入响应式对象

        ref对象





        reactive对象 





2. 侦听多个数据源

01 - 代码





02 - 效果

Vue3 之 Composition API_第15张图片

3. watch的选项

配置第三个参数 : 

  • deep : 是否深度监听
  • immediate : 是否立即执行

代码





十一、侦听数据的变化之watchEffect

1. watchEffect的基本使用

watchEffect : 

  • 自动收集响应式数据的依赖
  • watchEffect传入的函数会被立即执行一次,并且在执行的过程中会收集依赖
  • 只有收集的依赖发生变化时,watchEffect传入的函数才会再次执行

01 - 代码





02 - 效果 

Vue3 之 Composition API_第16张图片

2. watchEffect的停止监听

假如,某些情况想要停止监听,那么可以获取watchEffect的返回值函数,调用该函数即可

01 - 代码





02 - 效果 

Vue3 之 Composition API_第17张图片

3. watchEffect清除副作用

01 - 什么是清除副作用

  • 比如在开发中可能需要在侦听函数中执行网络请求,但是在网络请求还没有达到的时候,停止了侦听器,或者侦听器侦听函数被再次执行了
  • 那么上一次的网络请求应该被取消掉,这个时候就可以清除上一次的副作用

02 - 如何使用

  • 在给watchEffect传入的函数被回调时,其实可以获取到一个参数:onInvalidate
  • 当副作用即将重新执行 或者 侦听器被停止 时会执行该函数传入的回调函数
  • 可以在传入的回调函数中,执行一些清除工作

03 - 代码





04 - 效果 

Vue3 之 Composition API_第18张图片

4. watchEffect的执行时机

  • pre : 默认值,它会在元素 挂载 或者 更新 之前执行
  • post : 元素 挂载 或者 更新 之后执行
  • sync : 强制同步一起执行,效率很低,不推荐

一般来说,如果需要等dom挂载完后操作dom元素的时候,传post即可

代码





5. 和watch的区别

  • wathc必须指定数据源,watchEffect自动收集依赖
  • watch监听到改变,可以拿到改变前后的值,watchEffect只能拿到最新的值
  • watch第一次默认不执行,watchEffect默认直接执行一次

十二、自定义指令

1. 自定义指令的简单使用

Vue中自带的指令例如v-show、v-for、v-model等等,除了使用这些指令之外,Vue 也允许我们来自定义自己的指令

ps : 一般需要对dom元素进行底层操作时使用

自定义指令

  • 局部指令 : 组件中通过directives选项设定,只能在当前组件中使用
  • 全局指令 : app的directive方法,可以在任意组件中使用

栗子 : 实现input元素挂在完成后自动获得焦点

01 - 默认实现方式





02 - 局部指令





03 - 全局指令

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

// 指令名称
app.directive('focus', {
  // 使用自定义指令的生命周期,挂载后访问
  mounted(el, bindings, vnode, preVnode) {
    el.focus()
  }
})

app.mount('#app')

04 - 效果

Vue3 之 Composition API_第19张图片

2. 指令的生命周期

01 - Vue3

  • created:在绑定元素的 attribute 或事件监听器被应用之前调用
  • beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用
  • mounted:在绑定元素的父组件被挂载后调用 ( 常用 )
  • beforeUpdate:在更新包含组件的 VNode 之前调用
  • updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用
  • beforeUnmount:在卸载绑定元素的父组件之前调用
  • unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次

02 - Vue2 与 Vue3对比

Vue3 之 Composition API_第20张图片

3. 指令的参数和修饰符 





Vue3 之 Composition API_第21张图片

4. 时间显示栗子

01 - 代码

这里使用了dayjs,可以 npm install dayjs 安装一下





02 - 效果

十三、script setup语法糖

1. 概念

里面的代码会被编译成组件 setup() 函数的内容 : 

  • 这意味着与普通的

    3. 导入的组件直接使用

    
    
    

    4. defineProps()

    defineProps  =>  用来接收从父组件传递过来的数据

    01 - 父组件

    
    
    

    02 - 子组件

    
    
    

    5. defineEmits()

    defineProps  =>  用来发射事件给父组件

    01 - 子组件

    
    
    

    02 - 父组件

    
    
    

    6. defineExpose()

    defineExpose  =>  用来暴露数据

    ps : 使用

    02 - 父组件 

    
    
    

你可能感兴趣的:(Vue3,vue3,vue.js,前端,Vue3)