Vue3组合式API优点、声明响应式状态

1,379 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情juejin.cn/post/714765…

今天学习了很多关于vue3组合式api的知识,分享给大家。

组合式API

里面都是函数。在这里创建一个数据,是通过方法创建出来一堆数据

  1. 响应式API:
  2. 生命周期钩子:
  3. 依赖注入:

Vue3的组合式API优点

(1)有更高效的灵活性

处理相同逻辑关注点的代码被强制拆分在了不同的选项中,位于文件的不同部分。而组合式api里可以把功能相联系的代码放在一部分,维护起来也比较方便。

(2)更好的类型推导

TS就是里面接了强制类型系统。其他的和原来一模一样。如果没有声明类型,打包会报错。而vue里内置了这个类型推导(指的就是vue会自动帮我们加类型声明,而且基本不会错。)。所以它俩经常结合一起使用,vue从而对TS的支持更好。

(3)更小的生产包体积

选项式API是生成了一个对象。使用这里的方法和属性都需要通过this访问,对象(即this)里面的代码不好压缩。而组合式API里面可以直接使用,不需要使用this,所以压缩式会更好。

(4)更好的复用逻辑

Vue2中对逻辑复用都是放在mxins里,而组合式API解决了mixins的所有缺陷。 mixins的缺陷:

  1. 不清晰的数据来源:如果一个组件里使用多个mixins,多了就不知道具体来源于哪个mixins了。
  2. 命名冲突:组合式API里可以把引进来的进行重命名as
  3. 隐式的跨mixins交流。如果组件里使用了Amixins里的数据,而Amixins里的数据可能用到了Bmixins,这样的话就需要把Amixins和Bmixins都引入,比较麻烦。而Vue3中就是普通的函数传参。 取舍: 舍弃了选项式中手把手教我们该把代码放在哪里。例如Vue2中不用思考就知道事件函数就是放在methods里,组件就放在components里。

组合式API里的模板和选项式里的没有任何变化。

setup

声明响应式状态

通过reactive方法创建一个响应式的对象或数组。注意:reactive()只能创建对象和数组

3.png

import {reactive} from "vue";

//可以写多个reactive
const state = reactive({count:'0'});
//这样创建完以后count就是响应式的了。
//count改变视图就会更新
  • 组合式API里没有methods了,有watch和computed。直接把事件函数写在<script>标签内,也不需要在通过this访问。
  • DOM更新时机(和选项式API里是一样的,都是异步更新,可使用nextTick(()=> {})方法可立刻访问到最新的DOM)

深层响应性

在 Vue 中,状态都是默认深层响应式的。这意味着即使在更改深层次的对象或数组,你的改动也能被检测到。

  • 如果状态的值又是一个对象,深层对象改变也会更新view。
  • 可通过shallowReactive()方法创建浅层响应式
  • 如果一个对象经过proxy处理了,再把它经过proxy进行代理,得到的还是它本身。

reactive()的局限性

  1. 如果把state里的数据赋值给一个变量,改变这个变量,对state里的键值没影响。解构出来的也没影响
  2. 仅对对象类型有效(对象、数组和 MapSet 这样的集合类型),而对 stringnumber 和 boolean 这样的 原始类型 无效。 2.png

reactive()创建的响应式数据什么时候会丢失响应式?

解答:当我们将响应式对象的属性赋值或解构至本地变量时,或是将该属性传入一个函数时,我们会失去响应性

  • 可以用ref()方法定义响应式变量
  • 作用:该方法允许我们定义一个任何类型的值,并具有响应式。
 //通过ref创建响应式数据:
import { ref } from 'vue' 
count obj = ref( {num:0} )
//读取:obj.value.num
    
const count = ref(0);//0就是基础的number类型,是响应式的
读取:通过这种方式创建出来的count是个对象,所以读取时通过`count.value`读取.
    但注意:在模板里不需要.value直接写<div>{{count}}</div>
  • 这种方式创建内部也是调用了reactive方法。
  • ref在一般对象上时解构响应式不会丢失,也就是一个对象通过自面量式创建,键名自定义,键值是ref()方法返回的对象,进行解构时,不丢失响应式。
  • const object = { foo: ref(1) }
  • 不是顶层的ref()在模板中也会自动解包,相当于省略.value,但是如果想在模板中进行计算,必须加上.value,要不然的话时object.foo+1object.foo是个对象,模板输出直接输出对象,但是得到的是1这个值。所以不能直接做运算,想进行计算,需要通过obj.value.foo+1

ref 在响应式对象中的解包

1.png

 const count = ref(0) ;
 const state = reactive({ count });//这时候不需要写.value,会自动解包
  • 只有当嵌套在一个深层响应式对象内时,才会发生 ref 解包。当其作为浅层响应式对象的属性被访问时不会解包。
  • 跟响应式对象不同,当 ref 作为响应式数组或像 Map 这种原生集合类型的元素被访问时,不会进行解包。

ref响应性语法糖

注意:该方法在实验阶段。

<script setup> 
    let count = $ref(0) 
    function increment() { // 无需 .value ,就可以读取count的值
        count++ 
    } 
</script> 
<template>
    <button @click="increment">{{ count }}</button>
</template>

readonly()

接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理。 通俗的讲就是被readonly()方法包裹的数据是只读的,不能进行修改。