之前的blog【Naive UI】实现useDrawer hooks-优快云博客,提供了一种hooks方案以API的方式调用Naive UI的弹窗组件,在一般的单抽屉弹窗的业务场景下是没有问题的,但是后面发现,在打开一个抽屉后再打开新的抽屉,会出现问题:
关闭上层抽屉,会把所有的抽屉都关闭掉。
原因是因为按照原来的实现,抽屉组件创建时候都绑定了同一个show属性。
所以还是抽空进行了优化,友友们如果有引用到原来的代码实现,看到这,记得按我以下的源码给更新一下:
/*
* @Description : API方式使用抽屉组件
* @Author : Tanner
* @Date : 2024-05-30 11:03:33
*/
import { createApp, defineComponent, RenderFunction } from 'vue'
import { NConfigProvider, NDrawer, NDrawerContent, zhCN, dateZhCN, DrawerProps, DrawerContentProps } from 'naive-ui'
interface CreateDrawerProps {
drawerProps: DrawerProps;
drawerContentProps: DrawerContentProps;
content: RenderFunction;
[key: string]: any;
}
interface QueueItem {
show: Ref<boolean>;
drawer: ReturnType<typeof createApp> | null;
container: HTMLDivElement | null;
}
// 创建一个全局队列缓存drawer实例
const queue: QueueItem[] = []
export default function useDrawer() {
// 创建drawer
function createDrawer(props: CreateDrawerProps) {
// 每次创建一个新drawer就往队列加入新的实例和相关dom
queue.push({
show: ref(false),
drawer: null,
container: null
})
const { show } = queue.at(-1)!
// 定义drawer组件
const Drawer = defineComponent({
setup() {
nextTick(() => show.value = true)
},
render() {
return h(
NConfigProvider,
{
inlineThemeDisabled: true,
locale: zhCN,
dateLocale: dateZhCN
},
{
default: () => h(
NDrawer,
{
...props.drawerProps,
show: show.value,
onUpdateShow: (val: boolean) => {
if (!val) destroyDrawer()
}
},
{
default: () => h(
NDrawerContent,
props.drawerContentProps,
props.content
)
}
)
})
}
})
// 创建挂载元素
const container = document.createElement('div')
document.body.appendChild(container)
// 创建新应用,挂载到body
const drawer = createApp(Drawer, props)
drawer.mount(container)
queue.at(-1)!.drawer = drawer
queue.at(-1)!.container = container
return drawer
}
// 销毁drawer
function destroyDrawer() {
const { show, drawer, container } = queue.at(-1)!
show.value = false
// 抽屉关闭后,销毁队列最后一个drawer的实例和相关dom
setTimeout(() => {
drawer?.unmount()
container?.remove()
}, 320) // 等drawer关闭动画结束
queue.pop()
}
return {
createDrawer,
destroyDrawer
}
}
优化改造后,用法还是跟原来一样的,有更好的优化建议也欢迎评论留言。