vue3封装命令式弹窗组件

一、前言

相信大家都封装过弹窗组件,基本思路都是父组件给子组件传递一个变量,子组件props进行接收,当点击确认或者关闭按钮时,通过emit回传事件供父组件调用。这种封装方式缺点是复用性查、使用频繁时需要定义多份{isVisible、handleSubmit、handleClose}代码,代码冗余,今天分享一种命令式组件封装的方式。

二、什么是命令式组件

命令式组件封装是一种将功能封装在组件内部,并通过命令式的方式进行调用和控制的封装方法。在命令式组件封装中,组件负责封装一定的功能逻辑,并提供一组接口或方法,供外部代码调用来触发和控制组件的行为。调用方式大致为:

async function showMsg(){
    const [,res]= await msgBox('测试内容',{type:'success',iconType:'question'})
    if(res){
        consloe.log('点击了确定')
    }else{
        console.log('点击了取消')
    }
}

三、开始封装

首先创建一个MessageBox.vue文件,编写组件样式代码,这里我使用的是unocss进行编写。





组件需要接收参数

export interface HuiMsgBoxProp {
  /** 控制图标展示类型 info:叹号 success:钩 question:问号 */
  iconType:'info' | 'success' | 'question',
  /** 控制图标展示的颜色 */
  type:'info' | 'warning' | 'success' | 'danger',
  /** 弹窗显示的内容 */
  content:string,
  /** 取消按钮的文本 */
  cancelText:string,
  /** 确定按钮的文本 */
  confirmText:string,
  /** 关闭事件 */
  closeBox: ()=> void,
  /** 确定事件事件 */
  confirmHandler:()=> void,
  /** 取消事件 */
  cancelHandler:()=> void,
}

其次创建index.ts文件,由于组件调用方式是通过一个函数进行调用的,并提供.then.catch方法,所以需要编写一个函数,该函数返回一个Promise。当调用该函数,创建组件实例,组件进行挂载。

import { h, render } from 'vue'
import confirmComponent from './message-box.vue'
import { to } from "@hua5/hua5-utils"

export interface PayLoadType {
  /** 控制图标展示类型 info:叹号 success:钩 question:问号 */
  iconType?:'info' | 'success' | 'question',
  /** 控制图标展示的颜色 */
  type?: "info" | "success" | "danger" | "warning",
  /** 取消按钮的文本 */
  cancelText?:string,
  /** 确定按钮的文本 */
  confirmText?:string
}
export const hua5MsgBox = (content: string, payLoad:PayLoadType = {}) => {
  const { iconType = 'info', type = 'info', cancelText, confirmText } = payLoad
  return new Promise((resolve) => {
    // 取消按钮事件
    const cancelHandler = () => {
      resolve(false)
    }

    // 确定按钮事件
    const confirmHandler = () => {
      resolve(true)
    }

    // 关闭弹层事件
    const closeBox = () => {
      render(null, document.body)
    }

    // 1. 生成 vnode
    const vnode = h(confirmComponent, {
      content,
      iconType,
      type,
      cancelText,
      confirmText,
      cancelHandler,
      confirmHandler,
      closeBox,
    })

    // 2. render 渲染
    render(vnode, document.body)
  })
}

export const msgBox = (content: string, payLoad?:PayLoadType) => {
  return to(hua5MsgBox(content, payLoad))
}

四、to函数

/**
 * @param { Promise } promise
 * @param { Object= } errorExt - Additional Information you can pass to the err object
 * @return { Promise }
 */
export function to(promise: Promise): Promise {
  return promise.then(res => [null, res]).catch(error => [error, null])
}

你可能感兴趣的:(vue.js,前端,javascript)