一、函数调用式组件的需求
我们编写了Message组件,它可以有弹出提示、成功、错误等弹窗的功能。
现在我们的组件都是嵌套在组件树中展示的,但是Message组件使用这种方式会感觉比较奇怪,
<template>
<Message type=""></Message>
</template>
这个提示错误或成功的信息的组件:
它应该是像一个函数一样,进行工作的:就像alert一样,
调用一个函数,弹出提示,点击关闭,或者过一会儿消失。
createMessage('errorMessage', 'error')
这就是实现组件的一种方式:
函数调用式组件
创建了一个函数,叫createMessage
之前我们在message.vue里确定了3种类型,因为vue的文件类型对typescript支持有局限,我们没法直接把这个类型调用过来。
我们只能重新写一遍:
这里的难点是
怎样用函数的形式创建一个组件?
因为我们之前都是template实例化一个组件的
二、函数调用式组件的实现
我们在main.ts中有个createApp方法,可以看到createApp是从vue中直接导过来的,它可以生成组件的实例。
createApp文档
应用实例 API | Vue.js
createApp返回应用的实例,有两个参数:
第一个是“组件本身”,组件就是一个object,
第二个是props,组件接受的props
import { createApp } from "vue";
import Message from "./Message.vue";
export type MessageType = 'success' | 'error' | 'default'
const createMessage = (message: string, type: MessageType, timeout =2000) => { //timeout多久会消失
// 第一个参数是:组件对象,第二个参数是:props(和Message.vue组件里的props一一对应)
const messageInstance = createApp(Message, {
message,
type
})
}
export default createMessage
接下来,我们要挂载到一个DOM节点上,这样就可以显示在界面上。
main.ts也有这个逻辑,用mount方法挂载
main.ts
app.mount('#app')
src\components\createMessage.ts
// 那我们就新建一个节点,挂载到这个节点上
const mountNode = document.createElement('div')
document.body.appendChild(mountNode)
messageInstance.mount(mountNode)
// 它过一会儿要隐藏,所以我们设置延时,把它清空掉setTimoutout
setTimeout(() => {
messageInstance.unmount() // 卸载组件
document.body.removeChild(mountNode)// 同时把创建的节点也给删除掉
}, timeout)
我们方法写到这,接下来调用它
src\App.vue
// 先把原来的形式给删掉
<!--<message type="error" :message="error.message" v-if="error.status"></message> 当error.status为true的时候,message才会出现-->
// 删掉依赖:
components: {
// Message
},
// import Message from './components/Message.vue';
src\App.vue
添加:
import createMessage from './components/createMessage';
我们什么时候createMessage呢?
这里有一个error :computed ref
const error = computed(() => store.state.error)
这时候我们可以使用watch方法,当error发生变化的时候,watch其中的某一个值,当某值是我们想要的结果的时候,我们就显示错误提示。
watch可以接受getter的
src\App.vue
import { watch } from 'vue';
watch(() => error.value.status, () => {
const { status, message } = error.value
// status为真,并且message存在的时候,我们就显示错误提示。
if (status && message) { // 因为message可能是undefined,所以要加这个判断条件
createMessage(message, 'error') // error是三种类型之一
}
})
输入错误的用户名密码
弹出提示,2秒以后消失