函数调用式Message组件
3 years ago
# 编程
121
2
为什么需要函数式调用
函数式组件是使用vue中提供的h和render函数编写组件,可以在使用时只需要调用相应函数即可,不需要写在<template/>标签中,适合用来编写提示,Modal等组件。
例如Message组件
Message.vue 布局组件
<script setup lang="ts">
import { ref,onMounted } from 'vue'
const props = defineProps({
msg:{
type: String
},
onClose: {
type: Function,
required: false,
},
top:{
type: Number,
required: false
}
})
defineEmits(['destroy'])
const visible = ref(false)
function close(){
visible.value = false
}
function startTimer(){
setTimeout(()=>{
close()
},3000)
}
onMounted(() =>{
startTimer()
visible.value = true
})
defineExpose({
visible,
close,
})
</script>
<template>
<transition
@before-leave="onClose"
@after-leave="$emit('destroy')">
<div class="message" v-show="visible" :style="{top: props.top + 'px'}">
<div>{{props.msg}}</div>
</div>
</transition>
</template>
<style scoped>
.message{
/* border: 1px solid red; */
position: fixed;
top: 1rem;
left: 50%;
transform: translateX(-50%);
box-shadow: 0 3px 12px rgba(0,0,0,0.2);
padding: 6px 12px;
border-radius: 0.25rem;
user-select: none;
transition: top .2s;
}
.v-enter-active,
.v-leave-active {
transition: opacity 0.2s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>
Message/index.ts
import { createVNode, render, shallowReactive } from 'vue'
import type {VNode,ComponentInternalInstance} from 'vue'
import Message from './message.vue'
interface MessageContext {
id: string
vNode: VNode
vm: ComponentInternalInstance | null
props: any
}
export const instances = shallowReactive<MessageContext[]>([])
const message = (msg: string)=>{
createMessage(msg)
}
let seed = 1
function createMessage(msg: string){
let top = 12
if(instances.length){
let pre = instances[instances.length-1]
top = pre.props.top + 40
}
const container = document.createElement('div')
const props = {
msg,
top,
onClose: ()=>{
closeMessage(instance)
};
onDestroy: ()=>{
render(null,container)
console.log('destroy')
}
}
let vNode = createVNode(Message,props)
let vm = vNode.component
render(vNode,container)
document.body.appendChild(container.firstElementChild!)
const instance = {
id: `message_${seed++}`,
vNode,
vm,
props: vNode.component?.props
}
instances.push(instance)
return instance
}
function closeMessage(instance: MessageContext){
const idx = instances.findIndex(i=>i.id === instance.id)
if(idx === -1) return
instances.splice(idx,1)
console.log('closeMessage',idx)
instances.forEach((i) =>{
i.props.top -= 40
})
}
export default message
组件使用
<script setup lang="ts">
import Message from './components/Message'
function handleClick(){
Message("成功的消息")
}
</script>
<template>
<div>
<button @click="handleClick">Click</button>
</div>
</template>
文章标题:函数调用式Message组件
文章作者:灰色の青
最后修改时间: 2022 年 12 月 26 日 15:32
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
还没有人踏及此处,留下足迹吧