组合式 API 是一系列 API 的集合,使我们可以使用函数而不是声明选项的方式书写 Vue 组件。它是一个概括性的术语。
一个组件选项,在组件被创建之前,props 被解析之后执行。它是组合式 API 的入口。
setup 函数是个新的入口函数,相当于 vue2.x 中 beforeCreate 和 created,在 beforeCreate 之后 created 之前执行。
起初 Vue3.0 暴露变量必须 return 出来,template中才能使用;
这样会导致在页面上变量会出现很多次。
很不友好,vue3.2只需在script标签中添加setup。
可以帮助我们解决这个问题。
组件只需引入不用注册,属性和方法也不用返回,
也不用写setup函数,也不用写export default ,
甚至是自定义指令也可以在我们的template中自动获得。
<template>
<div class="app-container">
{{valueString}}
</div>
</template>
<script lang="ts">
import {
defineComponent,
reactive,
toRefs,
} from "vue";
// TIP: 若要对传递给 setup() 的参数进行类型推断,你需要使用 defineComponent。
export default defineComponent({
setup() {
const state = reactive({
rows: {},
dialog: {
open: false,
title: "",
},
valueString:"内容",
});
return {
...toRefs(state),
};
},
});
</script>
<template>
<div class="app-container">
{{valueString}}
<!-- 直接使用组件 -->
<Info ref="infoRefs" />
</div>
</template>
<script lang="ts" setup>
import Info from "./component/info.vue"; // 引入组件
// 响应式
const valueString:String = "内容";
</script>
getCurrentInstance 支持访问内部组件实例。
访问实例上下文,获取当前组件的实例、上下文等
import { getCurrentInstance } from 'vue';
// 获取当前组件实例
const instance = getCurrentInstance();
// 获取当前组件的上下文,下面两种方式都能获取到组件的上下文。
const { ctx } = getCurrentInstance(); // 方式一,这种方式只能在开发环境下使用,生产环境下的ctx将访问不到
const { proxy } = getCurrentInstance(); // 方式二,此方法在开发环境以及生产环境下都能放到组件上下文对象(推荐)
// ctx 中包含了组件中由ref和reactive创建的响应式数据对象,以及以下对象及方法;
proxy.$attrs
proxy.$data
proxy.$el
proxy.$emit
proxy.$forceUpdate
proxy.$nextTick
proxy.$options
proxy.$parent
proxy.$props
proxy.$refs
proxy.$root
proxy.$slots
proxy.$watch
getCurrentInstance 只暴露给高阶使用场景,典型的比如在库中。
强烈反对在应用的代码中使用 getCurrentInstance。
请不要把它当作在组合式 API 中获取 this 的替代方案来使用。
getCurrentInstance 只能在 setup 或生命周期钩子中调用。
如需在 setup 或生命周期钩子外使用,请先在 setup 中调用 getCurrentInstance() 获取该实例然后再使用。
<el-button type="primary" @click="submitForm">确定</el-button>
<script lang="ts">
import {
defineComponent,
onMounted,
reactive,
toRefs,
getCurrentInstance,
} from "vue";
export default defineComponent({
emits: ["reloadList"], // 子组件执行父组件方法
setup() {
const state = reactive({
rows: {},
dialog: {
open: false,
title: "",
},
});
const { proxy } = getCurrentInstance() as any; //有效
const Instance = getCurrentInstance(); //有效
// 点击事件
const submitForm = (): void => {
console.log("Instance", Instance); // 有效
getCurrentInstance(); // 无效
proxy.$emit("reloadList", "传值的内容");
};
// 生命周期
onMounted(() => {
getCurrentInstance(); // 有效
});
return {
handleAdd,
submitForm,
form,
...toRefs(state),
};
},
});
</script>
这些生命周期钩子注册函数只能在 setup() 期间同步使用,因为它们依赖于内部的全局状态来定位当前活动的实例 (此时正在调用其 setup() 的组件实例)。在没有当前活动实例的情况下,调用它们将会出错。
组件实例的上下文也是在生命周期钩子的同步执行期间设置的,因此,在生命周期钩子内同步创建的侦听器和计算属性也会在组件卸载时自动删除。
选项式 API 的生命周期选项和组合式 API 之间的映射
beforeCreate -> 使用 setup()
created -> 使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeUnmount -> onBeforeUnmount
unmounted -> onUnmounted
errorCaptured -> onErrorCaptured
renderTracked -> onRenderTracked
renderTriggered -> onRenderTriggered
activated -> onActivated
deactivated -> onDeactivated
使我们可以在使用响应性 API 时,利用 Vue 的依赖注入系统。
provide 和 inject 启用类似于 2.x provide / inject 选项的依赖项注入。
两者都只能在 setup() 当前活动实例期间调用。
provide 函数定义两个参数:
provide( name,value )
name:定义提供 property 的 name 。
value :property 的值。
**eg:**父组件传递参数 provide(“row”, 内容); // 父组件传值
import { provide } from "vue"
export default {
setup(){
provide("row", isAdoptOptions); // (有效)
// 点击详情向子组件提供单条数据
const handleInfo = (row: object) => {
proxy.$refs.infoRefs.handleInfo(row);
provide("row", isAdoptOptions); // 无效 接收的为undefined
};
}
}
inject 函数接收两个参数:
inject(name,default)
name:接收 provide 提供的属性名。
default:设置默认值,可以不写,是可选参数。【如果未提供默认值,并且在 Provide 上下文中找不到该属性,则 inject 返回 undefined。】
**eg:**子组件接收参数 inject(‘row’)
import { inject } from "vue"
export default {
setup(){
const rowsValue = inject('row')
onMounted(() => {
console.log('rowsValue',rowsValue)
});
return {
rowsValue
}
}
}