八、【Vue3】——组合式API(Composition API)

399 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

前言:Vue3中逻辑编码主要靠各种组合式API来实现的,这片主要列出编程中会经常使用到的API并进行分析,当然一些主要的API在以往章节详细介绍过的,可通过链接去学习。

1. 拉开序幕的setup

组件中所用到的:数据、方法等等,均要配置在setup中,因此setup是所有Composition API(组合API) “ 表演的舞台 ”。具体方法学习与注意点请参考我以往两片文章:

初始setup

setup不得不说的两个注意点

2. 响应式的refreactive函数

ref定义的一般是基本类型的响应式数据,reactive定义的一般是对象类型的响应式数据,以下两片文章详细介绍用法与响应式原理

ref函数&reactive函数用法

响应式原理

3. 计算属性与监视

监视watch有几个小坑,并且增加了watchEffect函数,更加智能化,具体请参考以下链接文章:

计算属性与监视

4. 生命周期函数

Vue3的生命周期钩子,除了可以通过像Vue2一样的配置项来实现外,还可以通过组合式API方式来实现。其中两个钩子方法名进行了变化和组合式API执行顺序请参考以下链接文档: Vue3生命周期

5. 自定义hook函数

类似于vue2.x中的mixin,并且可复用代码, 让setup中的逻辑更清楚易懂。

自定义hook函数

6. toReftoRefs函数

toRef:

  • 作用:创建一个ref对象,其value值指向另一个对象中的某个属性。
  • 语法:const name = toRef(person,'name')
  • 应用: 要将响应式对象中的某个属性单独提供给外部使用时
const state = reactive({
  foo: 1,
  bar: 2
})

const fooRef = toRef(state, 'foo')

fooRef.value++
console.log(state.foo) // 2

state.foo++
console.log(fooRef.value) // 3

toRefs:

  • 作用:创建多个ref对象,相当于将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref
const state = reactive({
  foo: 1,
  bar: 2
})

const stateAsRefs = toRefs(state)
/*
stateAsRefs 的类型:

{
  foo: Ref<number>,
  bar: Ref<number>
}
*/

// ref 和原始 property 已经“链接”起来了
state.foo++
console.log(stateAsRefs.foo.value) // 2

stateAsRefs.foo.value++
console.log(state.foo) // 3
  • 语法:const newPerson = toRefs(person)
  • 应用:当从组合式函数返回响应式对象时,toRefs 非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行解构/展开
  setup() {
    const state = reactive({
      foo: 1,
      bar: 2,
    })
    const stateAsRefs = toRefs(state)
        return {
                ...stateAsRefs
        }
  },
  • 解构优点:页面可以直接使用结构后的属性,不用每次使用前都加一层stateAsRefs
// 解构前:
<h2>foo:{{ stateAsRefs.foo }}</h2>
<h2>bar:{{ stateAsRefs.bar }}</h2>
// 解构后:
<h2>foo:{{ foo }}</h2>
<h2>bar:{{ bar }}</h2>

7. shallowReactiveshallowRef

  • shallowReactive:只处理对象最外层属性的响应式(浅响应式)。

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

  • 什么时候使用?

    • 如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive。
    • 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 ===> shallowRef。

8. readonlyshallowReadonly

  • readonly: 让一个响应式数据变为只读的(深只读)。
  • shallowReadonly:让一个响应式数据变为只读的(浅只读)。
  • 应用场景: 不希望数据被修改时。封装组件

9. toRawmarkRaw

toRaw:

  • 作用:将一个由reactive生成的响应式对象转为普通对象
  • 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。

markRaw:

  • 作用:标记一个对象,使其永远不会再成为响应式对象。
  • 应用场景:
    1. 有些值不应被设置为响应式的,例如复杂的第三方类库等。
    2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。

10. customRef

创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。通俗就是对其变化能进行追踪并写相应逻辑。

<template>
    <input type="text" v-model="keyWord">
    <h3>{{keyWord}}</h3>
</template>
<script>
    import {customRef} from 'vue'
    export default {
        name: 'App',
        setup() {
            //自定义一个ref——名为:myRef
            function myRef(value,delay){
                let timer
                return customRef((track,trigger)=>{
                    return {
                        get(){
                            // 步骤三:通知Vue追踪value的变化
                            track()
                            return value
                        },
                        set(newValue){
                            clearTimeout(timer)
                            timer = setTimeout(()=>{
                                // 步骤一:重新赋值 
                                value = newValue
                                // 步骤二:通知Vue去重新解析模板
                                trigger()
                            },delay)
                        },
                    }
                })
            }
            let keyWord = myRef('hello',500) //使用程序员自定义的ref
            return {keyWord}
        }
    }
</script>

初始时调动get进行页面解析 更改文本框中的值时调用set,此时运行步骤如下:

  1. set函数中重新赋值:value = newValue
  2. 通知Vue去重新解析模板:trigger()
  3. 页面重新解析模版时,还会去调用get获取值;
  4. 通知Vue追踪value的变化:track(); 注:
  • 如果set函数中不写trigger(),input框变化时,不会重新解析模版;
  • 如果get函数中不写track(),get函数会认为已经初始化解析过一次,不会重新解析新值返回;

11. provideinject

  • 作用:实现祖与后代组件间通信

  • 套路:父组件有一个 provide 选项来提供数据,后代组件有一个 inject 选项来开始使用这些数据

  • 具体写法:

    1. 祖组件中:
    setup(){
      ......
        let car = reactive({name:'奔驰',price:'40万'})
        provide('car',car)
        ......
    }
    
    1. 后代组件中:
    setup(props,context){
      ......
        const car = inject('car')
        return {car}
      ......
    }
    

12.响应式数据的判断

  • isRef: 检查一个值是否为一个 ref 对象
  • isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
  • isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
  • isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理

13. Composition API 的优势

Options API 存在的问题

使用传统OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改 。通常一个工程文件中数据量较多,则使得阅读与维护不方便

2.Composition API 的优势

我们可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起。