【Naive UI】实现useDrawer hooks后续优化

之前的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
  }
}

优化改造后,用法还是跟原来一样的,有更好的优化建议也欢迎评论留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值