【Naive UI】实现useDrawer hooks

最近在使用Vue3 + Vite + Naive UI开发新项目,发现Naive对于dialog,model组件都提供了API方式的调用实现,同时支持传入render函数,可以轻松地实现弹出式的组件功能。

但是同样是弹出式组件的抽屉(drawer)却被不公平对待😡, 居然没提供API方式的调用,只能老老实实在template引入使用,这简直无法忍受,网上查了一圈没有找到相关的实现,到官方github的Issues居然没人提这个需求😮,所以我以hooks方式自己实现一个useDrawer。

直接上代码:

// @/hooks/useDrawer.ts

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;
}

export default function useDrawer() {
  const show = ref(false)

  // 创建drawer
  function createDrawer(props: CreateDrawerProps) {
    // 定义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) => { show.value = val }
              },
              {
                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)

    // 抽屉关闭后,销毁挂载元素和相关dom
    const stopWatcher = watch(show, (val) => {
      if (val) return
      stopWatcher()
      setTimeout(() => {
        container.remove()
        const drawerContainer = document.getElementsByClassName('n-drawer-container')
        drawerContainer[drawerContainer.length - 1]?.remove()
      }, 320) // 等drawer关闭动画结束
    })
    return drawer
  }

  // 销毁drawer
  function destroyDrawer() {
    show.value = false
  }

  return {
    createDrawer,
    destroyDrawer
  }
}

 使用方式:

/**
 * @description 测试useDrawer
 */

const { createDrawer, destroyDrawer } = useDrawer()
const test = () => {
  createDrawer({
    // 这里的drawerProps跟文档上的Drawer Props保持一致
    drawerProps: {
      width: 500
    },
    // 这里的drawerContentProps跟文档上的DrawerContent Props保持一致
    drawerContentProps: {
      title: '标题',
      closable: true
    },
    // ChildComponent为自定义的子组件,通过props传值,emit派发事件
    content: () => h(ChildComponent, {
      detail: { id: '123' },
      onCancel: () => {
        destroyDrawer()
      },
      onConfirm: () => {
        destroyDrawer()
      }
    })
  })
}

就是这样自己实现了一个Naive UI的userDrawer,使用起来优雅而方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值