- Published on
Vue3 开发解决方案(二)
- Authors
- Name
- Deng Hua
目录
封装 Confirm 组件
confirm 组件的实现思路:
创建
confirm
组件创建一个函数组件并返回一个
promise
使用h函数生成
confirm
组件的vnode
最后,使用
render
函数将vnode
渲染为body
了解了组件的设计思想之后,我们需要分析它应该具备的props。
const props = defineProps({
title: {
type: String
},
content: {
type: String,
required: true
},
cancelText: {
type: String,
default: 'Cancel'
},
confirmText: {
type: String,
default: 'Confirm'
},
// 取消和确认时触发事件
closeAfter: {
type: Function
},
// 确认时触发事件
handleConfirmClick: {
type: Function
},
// 取消时触发事件
handleCancelClick: {
type: Function
}
})
当弹出框出现时,我们需要监听mounted事件,然后显示遮罩和弹出框。
当点击关闭弹框的时候,不能立即卸载该组件,否则动画会立即消失,所以延迟卸载执行。
// 动画持续时间
const actionDuration = '0.5s'
const isVisible = ref(false)
onMounted(() => {
isVisible.value = true
})
const handleClose = () => {
isVisible.value = false
setTimeout(() => {
// 卸载“confirm”组件
props.closeAfter()
}, parseInt(actionDuration.replace('0.', '').replace('s', '')) * 100)
}
函数组件的封装主要使用 h
, render
函数操作。
closeAfter
: 主要是点击任意位置关闭弹框时卸载组件。handleConfirmClick
: 当确认按钮被点击的时候,promise的状态就被fulfilled了,这样当外部使用该功能组件的时候,已确认的事情可以在之后进行操作。handleCancelClick
:当点击取消按钮时,promise状态被rejected,当外部使用函数组件时,可以在catch中操作被取消的东西。
后两个函数主要是为了区分你点击的是“取消”还是“确认”。
import { h, render } from 'vue'
import Confirm from './index.vue'
export default function createConfirm({
title,
content,
cancelText = 'Cancel',
confirmText = 'Confirm'
}) {
return new Promise((resolve, reject) => {
const closeAfter = () => {
render(null, document.body)
}
/**
* 点击“confirm”按钮时回调
*/
const handleConfirmClick = resolve;
/**
* 单击“cancel”按钮时回调
*/
const handleCancelClick = reject;
// 创建“vnode”并传递“props”
const vnode = h(Confirm, {
title,
content,
cancelText,
confirmText,
closeAfter,
handleConfirmClick,
handleCancelClick
})
// 在“body”中渲染组件
render(vnode, document.body)
})
}
封装 Message 组件
消息组件的实现与confirm
非常相似。
props需要指定弹出时间和类型:
const props = defineProps({
type: {
type: String,
required: true,
validate(val) {
if (types.includes(val)) {
return true
} else {
throw new Error('Please pass in a correct type value (error, warn, success)')
}
}
},
content: {
type: String,
required: true
},
closeAfter: {
type: Function
},
delay: {
type: Number,
default: 3000
}
})
const isVisible = ref(false)
onMounted(() => {
isVisible.value = true
setTimeout(() => {
isVisible.value = false
}, props.delay)
})
import { h, render } from 'vue'
import Message from './index.vue'
export function createMessage({ type, content, delay = 3000 }) {
const closeAfter = () => {
render(null, document.body)
}
const vnode = h(Message, {
type,
content,
delay,
closeAfter
})
render(vnode, document.body)
}