Vue3 组合式API 的使用

5,298 阅读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

definePropsdefineEmits

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

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

const emit = defineEmits(['change', 'delete'])
// setup code
</script>
  • definePropsdefineEmits 都是只在 <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 会和在普通实例中一样被自动解包)