Vue 3 的组合式 API(Composition API)是一组函数和语法糖,用于更灵活和可组合地组织 Vue 组件的代码逻辑。与 Vue 2 的 Options API 不同,组合式 API 不再以选项的形式存在,而是通过 标签来使用。
组合式 API 提供了以下几个核心函数:
setup()
:组件创建之前调用的函数,用于定义组件的状态、计算属性、方法、事件等。setup()
函数可以返回一个对象,包含模板中需要用到的数据和方法。ref()
:接收一个初始值并返回一个响应式对象,可以通过 .value
属性获取或修改值。reactive()
:接收一个普通对象并返回一个响应式的对象,内部所有属性都是响应式的。computed()
:接收一个计算函数作为参数,返回一个响应式的计算属性。watch()
:监听数据变化并执行回调函数。onMounted()
、onUpdated()
、onUnmounted()
:生命周期钩子函数,分别在组件挂载、更新和卸载时调用。使用组合式 API 的好处包括:
组合式 API 可以与 Options API 共存,因此可以按需选择使用。
新建项目后在根组件中重新生成vue
然后删掉script
标签内代码全部删掉
<template>
<div>
{{ name }}
div>
template>
<script setup>
let name = '张三'
script>
<style scoped>
style>
其中name
是一个响应式的数据属性,初始值为 ‘张三’
在模板中使用插值语法 {{}}
来动态展示 name 属性的值
上面的例子比较简单,下面看简单类型加上ref
封装变成响应式数据
<template>
<div>
{{ name }}
<br>
<button @click="change">换名字</button>
</div>
</template>
<!-- 加上setup就是组合式API -->
<script setup>
let name = '张三'
function change(){
name = '张三去打水了'
}
</script>
<style scoped>
</style>
运行后代码并没有改变
定义的数据默认不支持响应式(代码一变立刻同步到视图上,配置式API默认支持)
import {ref} from 'vue'
组合式API想把数据变成响应式的,需要用ref
对数据做一个封装
简单类型需要用ref
进行封装,而对象类型不需要
.value
属性<template>
<div>
{{ name }}
<br>
<button @click="change">换名字</button>
</div>
</template>
<!-- 加上setup就是组合式API -->
<script setup>
import {ref} from 'vue'
let name = ref ('张三')
function change(){
name.value = '张三去打水了'
}
</script>
<style scoped>
</style>
<template>
<div>
{{ name }}--{{ user.name }}
<br>
<button @click="change">换名字</button>
</div>
</template>
<!-- 加上setup就是组合式API -->
<script setup>
import {ref} from 'vue'
let name = ref ('张三')
// 对象类型
let user = {
name: '李四'
}
function change(){
name.value = '张三去打水了'
user.name = '李四去挑水'
}
</script>
<style scoped>
</style>
在上面的代码中,user 对象的 name 属性值为 ‘李四’,该属性与 name 响应式变量不同,二者无关。
在模板中,{{ user.name }} 用于显示 user 对象的 name 属性值,而 {{ name }} 则用于显示 name 响应式变量的值。
之前使用子组件是导入、注册、使用,在组合式API内是导入之后直接使用
导入:
import HelloWorld from '@/components/HelloWorld.vue';
使用:
<HelloWorld></HelloWorld>
<template>
<div>
{{ name }}--{{ user.name }}
<br>
<p v-for="(item, index) in arr" :key="index">{{ item }}</p>
<button @click="change">换名字</button>
<HelloWorld></HelloWorld>
</div>
</template>
<!-- 加上setup就是组合式API -->
<script setup>
import {ref} from 'vue'
import HelloWorld from '@/components/HelloWorld.vue';
let name = ref ('张三')
// 对象类型
let user = {
name: '李四'
}
//数组类型
let arr = ['a','b','c']
function change(){
name.value = '张三去打水了'
user.name = '李四去挑水'
arr.splice(0,1)
}
</script>
<style scoped>
</style>
接下来也给数组封装一下reactive
<template>
<div>
{{ name }}--{{ user.name }}
<br>
<p v-for="(item, index) in arr" :key="index">{{ item }}</p>
<button @click="change">换名字</button>
<HelloWorld></HelloWorld>
</div>
</template>
<!-- 加上setup就是组合式API -->
<script setup>
import {ref,reactive} from 'vue'
import HelloWorld from '@/components/HelloWorld.vue';
let name = ref ('张三')
// 对象类型
let user = {
name: '李四'
}
//数组类型
let arr = reactive(['a','b','c'])
function change(){
name.value = '张三去打水了'
user.name = '李四去挑水'
arr.splice(0,1)
}
</script>
<style scoped>
</style>
新建两个子组件:Add、List,生成基本结构后删除script
标签内默认生成的配置项
根组件中:
使用了
组件,该组件的代码未展示,可以理解为列表组件;
引入了 reactive
函数,创建了一个响应式的数组 arr
,用于存储待办列表中的数据
<template>
<div>
<h1>待办列表</h1>
<List></List>
</div>
</template>
<script setup>
import List from '@/components/List.vue'
import { reactive } from 'vue';
// 定义数组
let arr = reactive(['看电影','玩游戏'])
</script>
<style scoped>
</style>
List子组件中
在列表组件 中,使用了
defineProps
函数来定义组件的属性,可以用于定义组件的 props
。在这里定义了一个 list 属性,类型为数组类型 Array。
在模板中,使用了 v-for
循环遍历 list 数组中的数据,然后使用 {{ item }}
渲染每一项的数据。这里加上了 :key="index"
,以便 Vue 可以快速识别每个列表项,并渲染正确的数据。
<template>
<div>
<ol>
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ol>
</div>
</template>
<script setup>
// 组合式写法,自定义属性
let myProps = defineProps({
list :{type: Array}
})
</script>
<style scoped>
</style>
接下来在父组件中传递一个属性数据
<List :list="arr"></List>
接下来在父组件中传入子组件App
import Add from '@/components/Add.vue';
<Add @item="recive"></Add>
function recive(v) {
arr.push(v)
}
接下来就剩子组件Add了
<template>
<div>
<input type="text" v-model="item">
<button @click="send">添加</button>
</div>
</template>
<script setup>
// 定义事件 数据名item
import {ref} from 'vue'
let item = ref('')
// 定义事件 send
// 组合式API自定义事件
let emits = defineEmits(['item'])
function send(){
if ( item.value!='' ) {
// 不为空 发送数据
emits('item',item.value)
// 清空输入框,避免重复添加
item.value = ''
}
}
</script>
<style scoped>
/* 输入框样式 */
input {
padding: 8px 16px;
font-size: 16px;
outline:none;
border: 1px solid black;
border-radius: 4px;
margin-right: 8px;
}
/* 按钮样式 */
button {
padding: 8px 16px;
font-size: 16px;
background-color: #409EFF;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
以下是对代码的注释和步骤的解释:
<template>
<div>
<h1>待办列表h1>
<Add @item="recive">Add>
<List @remove="del" :list="arr">List>
div>
template>
上面的代码是 App.vue
文件的模板部分,主要是引入 Add.vue
和 List.vue
组件,并绑定对应的自定义事件。
<script setup>
import List from '@/components/List.vue'
import Add from '@/components/Add.vue'
import { reactive } from 'vue'
// 定义数组
let arr = reactive(['玩游戏','看电影'])
function recive(v){
arr.push(v)
}
function del(i){
arr.splice(i,1)
}
</script>
上面的代码是 App.vue
文件的逻辑部分。引入 List.vue
和 Add.vue
组件,并用 reactive
定义了一个响应式数组 arr
,用于存储待办列表。
recive
函数用于接收从 Add.vue
组件传递过来的数据,并将其添加到 arr
数组中。
del
函数用于接收从 List.vue
组件传递过来的数据,并将对应的列表项从 arr
数组中删除。
<template>
<div>
<input type="text" v-model="item">
<button @click="send">添加button>
div>
template>
上面的代码是 Add.vue
文件的模板部分,主要包含一个输入框和一个按钮,用于向父组件派发数据。
<script setup>
// 定义事件 数据名item
import {ref} from 'vue'
let item = ref('')
// 定义事件 send
// 组合式API自定义事件
let emits = defineEmits(['item'])
function send(){
if ( item.value!='' ) {
// 不为空 发送数据
emits('item',item.value)
// 清空输入框,避免重复添加
item.value=''
}
}
</script>
上面的代码是 Add.vue
文件的逻辑部分,用 defineEmits
定义了一个自定义事件 item
,用 ref
定义了一个响应式变量 item
,用于获取输入框内的值。当点击添加按钮时,根据输入框内的值,触发自定义事件并将输入框内的值作为参数传递给父组件,最后清空输入框。
<template>
<div>
<ol>
<li @click="send(index)" v-for="(item, index) in list" :key="index">{{ item }}li>
ol>
div>
template>
上面的代码是 List.vue
文件的模板部分,主要用于展示待办列表。
<script setup>
//组合式写法 自定义属性
let myProps = defineProps({
list:{type: Array}
})
let emits = defineEmits(['remove'])
function send(i){
emits('remove',i)
}
</script>
上面的代码是 List.vue
文件的逻辑部分,用 defineProps
定义了一个 list
属性,用于接收父组件传递过来的数据。用 defineEmits
定义了一个自定义事件 remove
,当每个列表项被点击时触发该事件,并向父组件派发一个消息。
上面的代码是 List.vue
文件的样式部分,主要用于美化待办列表的样式。