Vue3 - composition Api
- setup中的函数
- (1)computed函数使用
- (2)setup获取元素或组件
- (3)组件的生命周期函数
- (4)provide/inject函数(了解)
- (5)watch/watchEffect
- (6)script setup语法(重要)
setup中的函数
(1)computed函数使用
在前面我们讲解过计算属性computed:当我们的某些属性是依赖其他状态时,我们可以使用计算属性来处理
- 在前面的Options API中,我们是使用computed选项来完成的;
- 在Composition APl中,我们可以在setup 函数中使用computed方法来编写一个计算属性
如何使用computed呢?
方式一
:接收一个getter函数
,并为getter函数返回的值,返回一个不变的ref对象;方式二:
接收一个具有get和set的对象
,返回一个可变的(可读写) ref对象;
方式一示例:
<template>
<div class="app">
<h2>{{ fullNmae }}</h2>
</div>
</template>
<script>
import { reactive, computed } from 'vue';
export default {
setup() {
// 1.定义数据
const names = reactive({
firstName: "kobe",
lastName: "bryant"
})
const fullNmae = computed(() => {
return names.firstName + " " + names.lastName
})
return {
fullNmae,
}
}
}
</script>
方式二示例:
setup() {
const name = reactive({
firstName: "kobe",
lastName: "Bryant"
})
// 既有getter函数又有setter函数, 需要传入一个对象作为参数
const fullName = computed({
// set函数 会返回一个可变的ref对象
set: newValue => {
const names = newValue.split(" ")
name.firstName = names[0]
name.lastName = names[1]
},
get: () => {
return name.firstName + " " + name.lastName
}
})
// 因为返回的是ref对象, 所以通过fullName.vlue设置fullName的值
fullName.value = "aaa bbb"
return {
fullName
}
}
(2)setup获取元素或组件
在setup中,禁用this,如何使用ref获取元素或组件呢?
ref在setup中的使用:
- 只需要
定义一个ref对象
,绑定到元素或者组件的ref属性
上即可;
使用示例:
<template>
<!-- 1.获取元素 -->
<h2 ref="titleRef">我是标题</h2>
<button ref="btnRef">按钮</button>
<hr>
<!-- 2.获取组件实例 -->
<ShowInfo ref="showinfoRef"></ShowInfo>
</template>
<script>
import { onMounted, ref } from "vue";
import ShowInfo from './ShowInfo.vue'
export default {
// 之前获取元素的做法
// mounted(){
// console.log(this.$refs.title);
// console.log(this.$refs.button);
// },
components: {
ShowInfo
},
setup() {
//定义ref对象并绑定元素或组件上的ref属性
const titleRef = ref()
const btnRef = ref()
const showinfoRef = ref()
// mounted的生命周期函数
onMounted(() => {
console.log(titleRef.value);
console.log(btnRef.value);
console.log(showinfoRef.value);
showinfoRef.value.showinfoSum()
})
return {
titleRef,
btnRef,
showinfoRef
}
}
}
</script>
(3)组件的生命周期函数
我们前面说过setup 可以用来替代data,methods、computed等等这些选项,也可以替代生命周期钩子
。
那么setup中如何使用生命周期函数呢?
- 可以使用直接导入的
onX函数注册生命周期钩子
;
以前的生命周期和composition API中的生命周期钩子对比图:
我们发现beforeCreat和created
两个生命周期钩子在setup中没有对应的hook
,官方给出的解释如下:
(4)provide/inject函数(了解)
事实上我们之前还学习过Provide和Inject,Composition API也可以替代之前的Provide和 Inject的选项。
我们可以通过provide来提供数据:
- 可以通过provide方法来定义每个 Property;
provide可以传入两个参数:
- name:提供的属性名称;
- value:提供的属性值;
import { provide } from 'vue'
export default {
setup() {
// 将导出数据设置为响应式
const name = ref("chenjg")
const age = ref(20)
provide("name", name)
provide("age", age)
}
}
在后代组件中可以通过 inject 来注入需要的属性和对应的值:
inject可以传入两个参数:
- inject 的 property 的 name;
- 默认值;
setup() {
const name = inject("name", "默认值")
const age = inject("age")
return {
name,
age
}
}
(了解即可,在vue2中多使用vueX,vue3中使用pinia来进行复杂在数据管理)
(5)watch/watchEffect
在前面的Options API中,我们可以通过
watch选项
来侦听data或者props
的数据变化,当数据变化时执行某一些操作。在Composition APl中,我们可以使用
watchEffect和watch
来完成响应式数据的侦听;
watchEffect:
用于自动收集响应式数据的依赖;watch:
需要手动指定侦听的数据源;
watch的使用:
watch的API完全等同于组件watch选项的Property:
- watch需要
侦听特定的数据源
,并且执行其回调函数; - 默认情况下它是惰性的,只有当被侦听的源发生变化时才会执行回调;
setup() {
let message = ref("hello world")
watch(message, (oldValue, newValue) => {
console.log(oldValue, newValue)
})
function btnClick() {
message.value = "oooooo"
}
return {
message,
btnClick
}
}
侦听器还可以使用数组同时侦听多个源:
setup() {
let message = ref("hello world")
const name = ref("kobe")
watch([message, name], (oldValue, newValue) => {
console.log(oldValue, newValue)
})
function btnClick() {
message.value = "oooo"
name.value = "sevgilid"
}
return {
message,
btnClick,
name
}
}
额外补充:
watchEffect的使用
当侦听到某些响应式数据变化时,我们希望执行某些操作,这个时候可以使用watchEffect
。
我们来看一个案例:
- 首先,watchEffect传入的函数会被立即执行一次,并且在执行的过程中会收集依赖;
- 其次,只有收集的依赖发生变化时,watchEffect传入的函数才会再次执行;
setup() {
let message = ref("hello world")
const name = ref("kobe")
watchEffect(() => {
console.log("wactchEffect执行", message.value, name.value)
})
}
watchEffect的停止侦听:
当侦听某些响应式数据变化,我们希望执行某些操作时,比如停止侦听,这个时候我们可以获取watchEffect的返回值函数,调用该函数即可。
- 比如在下面的案例中,我们counter达到10的时候就停止侦听:
setup() {
const counter = ref(0)
// 当侦听某些响应式数据变化,我们希望执行某些操作时,这时候可以使用watchEffect
//1. watcheffect传入的函数会立即执行一次,并且在执行过程中会收集依赖
const stopWatch = watchEffect(() => {
console.log("-------", counter.value);
//2. 当依赖发生变化时,函数会再次执行
// 判断counter.value>=10 停止监听
if (counter.value >= 10) {
stopWatch()
}
})
return {
counter
}
}
(6)script setup语法(重要)
基本使用:
< script setup > 是在单文件组件(SFC)中使用组合式API的编译时语法糖,当同时使用SFC与组合式APl时则推荐该语法。
- 更少的样板内容,更简洁的代码;
- 能够使用纯 Typescript声明prop和抛出事件;
- 更好的运行时性能;
- 更好的IDE类型推断性能;
使用这个语法,需要将setup attribute添加到< script >代码块上:
里面的代码会被编译成组件setup()函数的内容:
- 这意味着与普通的< script >只在组件被首次引入的时候执行一次不同;
- < script setup >中的代码会在每次组件实例被创建的时候执行。
顶层的绑定会被暴露给模板
当使用< script setup >的时候,任何在< script setup >声明的顶层的绑定(包括变量,函数声明,以及import引入的内容)都能在模板中直接使用:
<script setup>
// 1.所有编写在顶层的代码,都是默认暴露给template可以使用
import { onMounted, ref } from "vue";
import ShowInfo from "./ShowInfo.vue";
// 2.定义响应式数据
const message = ref("hello world")
// 3.定义函数
function changeMessage() {
message.value = "message已被改变"
}
function infobtnClick(payload) {
console.log("监听到showinfo内部的点击:", payload);
}
const ShowInfoRef = ref()
onMounted(() => {
ShowInfoRef.value.foo()
})
</script>
<!-- script放中间和顶部都可以:但放在上面可以使template和css编辑距离较近 -->
导入的组件直接使用
<template>
<div class="app">
<!-- 引入子组件同样直接使用 -->
<show-info />
</div>
</template>
<script setup>
// 引入子组件, 无需注册, 引入即可使用
import ShowInfo from "./ShowInfo.vue"
}
</script>
defineProps() 和 defineEmits()
为了在声明props和emits 选项时获得完整的类型推断支持,我们可以使用defineProps和defineEmits API,它们将自动地在< script setup >中可用:
(1) 如果父组件需要向子组件传递传递属性, 接收时需要用到defineProps()方法
(2)子组件发送事件就需要defineEmits()方法
代码示例:
<template>
<div>showinfo:{{ name }} - {{ age }}</div>
<button @click="showInfoBtnClick">showinfoButton</button>
</template>
<script setup>
// 不使用语法糖的scrip标签里接收父组件传参时使用props{}
// 使用语法糖时,定义props时使用defineProps()函数
defineProps({
name:{
type:String,
default:"无名氏"
},
age:{
type:Number,
default:0
}
})
// 发送事件
// 以前:emmits:[""]
const emits = defineEmits(["infoClick"])
function showInfoBtnClick(){
emits("infoClick","showinfo内部发生了点击")
}
</script>
defineExpose()
使用< script setup >的组件是默认关闭的:
- 通过模板ref或者$parent链获取到的组件的公开实例,不会暴露任何在< script setup >中声明的绑定;
通过defineExpose编译器宏来显式指定在< script setup >组件中要暴露出去的property: