Vue3 组合式API 的使用

5,458 阅读3分钟

组合式API

组合式API其实从字面上看就是把各种方式组合起来,像搭积木那样的。使用组合式API我们需要知道以下几个知识点:

setup组件选项

setup就是组合式api的入口,和vue2中的data、computed、watch、methdos一样,定义了一个组合式API的入口。大致代码如下:

<template>
    <div>
        {{counter}}
    </div>
</template>

<script>
import { ref } from 'vue'
export default {
  name: 'Home',
  setup(props,context){
    console.log(props,context)
    const counter = ref(0)
    
    return {
        counter
    }
  }
}
</script>

上面的setup里面的就是组合式API。组合式API其实就是把之前Vue2分散在data、生命周期、watch、computed、methods中的部分现在全部整合到一起放到了setup中,这样的好处就是我们可以把一些业务或者逻辑抽离出来,然后那个地方需要就直接引入,比vue2中的方便了一些。

script setup 语法糖

setup script就是vue3新出的一个语法糖,使用方法就是在书写script标签的时候在其后面加上一个setup修饰。

代码如下:

<template>
    <div>
        {{counter}}
    </div>
</template>

<script setup>
import { ref } from 'vue'
const counter = ref(0)
</script>

setup script 的好处

  1. 自动注册组件
  2. 属性和方法无需返回

使用 this

在 setup() 内部,this 不是该活跃实例的引用,因为 setup() 是在解析其它组件选项之前被调用的,所以 setup() 内部的 this 的行为与其它选项中的 this 完全不同。这使得 setup() 在和其它选项式 API 一起使用时可能会导致混淆。

响应式变量的定义

1. ref() 函数

ref() 函数用来根据给定的值创建一个响应式的数据对象,传入的为基本数据类型,例如字符串、数字、boolean 等,返回值是一个对象,这个对象上只包含一个 value 属性

ref定义的变量,改变值要.value,而且在template中不用写.value

<template>
	<div>{{count}}</div>
	<button @click="setCount">修改</button>
</template>

<script setup>
import { ref } from 'vue'
import HelloWorld from '@/components/HelloWorld.vue'

// 定义
const count = ref(0)

// 修改
const setCount = () => {
    count.value = count.value + 1
}
</script>

2. reactive() 函数

reactive() 函数传入的为引用类型,例如数组、对象等,但不能代理基本类型值,返回一个响应式的数据对象,

想要使用reactive()函数创建的响应式数据也很简单,创建出来之后直接在template中调用即可。

<template>
	<div>{{state.msg}}</div>
	<button @click="setMsg()">修改</button>
</template>

<script setup>
import { reactive } from 'vue'

    //定义
    const state = reactive({
        msg: '你好',
        msg2:'hello'
    })
    //修改
    const setMsg = () => {
        state.msg = 'msg被改了'
    }
</script>

3. 为子组件或html元素绑定refs

<template>
	<div>哈哈哈</div>
	<HelloWorld ref='helloWorldRef'></HelloWorld>
</template>

<script setup>
import { ref } from 'vue'
import HelloWorld from '@/components/HelloWorld.vue'
    
const helloWorldRef = ref()
</script>

在setup 中使用watch

在setup中watch作为一个函数接受三个参数:监听的值、回调、可选的配置。实例如下:

<script setup>
import { ref, watch } from 'vue'
    
const counter = ref(0)

watch(counter, (newValue, oldValue) => {
   console.log(counter.value)
})
    
</script>

在setup中使用computed

<script setup>
import { ref, computed } from 'vue'
    
const counter = ref(0)
const twiceTheCounter = computed(() => counter.value * 2)

counter.value++
    
console.log(counter.value) // 1
console.log(twiceTheCounter.value) // 2
    
</script>

生命周期钩子

选项式 API调用时机setup
beforeCreate在实例初始化之后、进行数据侦听和事件/侦听器的配置之前同步调用。不需要
created在实例创建完成后被立即同步调用不需要
beforeMount在挂载开始之前被调用onBeforeMount
mounted在实例挂载完成后被调用onMounted
beforeUpdate在数据发生改变后,DOM 被更新之前被调用onBeforeUpdate
updated在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用onUpdated
beforeUnmount在卸载组件实例之前调用onBeforeUnmount
unmounted卸载组件实例后调用onUnmounted
errorCaptured在捕获一个来自后代组件的错误时被调用onErrorCaptured
renderTracked跟踪虚拟 DOM 重新渲染时调用onRenderTracked
renderTriggered当虚拟 DOM 重新渲染被触发时调用onRenderTriggered
activated被 keep-alive 缓存的组件激活时调用。onActivated
deactivated被 keep-alive 缓存的组件失活时调用。onDeactivated

defineProps 和 defineEmits

在 <script setup> 中必须使用 defineProps 和 defineEmits API 来声明 props 和 emits ,它们具备完整的类型推断并且在 <script setup> 中是直接可用的:

<script setup>
const props = defineProps({
  foo: {
    type: String, // 类型
    required: true, // 是否必填
    default: "请输入" // 默认值
  }
})

const emit = defineEmits(['change', 'delete'])
// setup code
</script>
  • defineProps 和 defineEmits 都是只在 <script setup> 中才能使用的编译器宏。他们不需要导入且会随着 <script setup> 处理过程一同被编译掉。
  • defineProps 接收与 props 选项相同的值,defineEmits 也接收 emits 选项相同的值。

defineExpose

使用 <script setup> 的组件是默认关闭的,也即通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定。

为了在 <script setup> 组件中明确要暴露出去的属性,使用 defineExpose 编译器宏:

<script setup>
import { ref } from 'vue'

const a = 1
const b = ref(2)

defineExpose({
  a,
  b
})
</script>

当父组件通过模板 ref 的方式获取到当前组件的实例,获取到的实例会像这样 { a: number, b: number } (ref 会和在普通实例中一样被自动解包)