Published on

Vue3 开发解决方案(二)

Authors
  • avatar
    Name
    Deng Hua
    Twitter

目录

封装 Confirm 组件

confirm 组件的实现思路:

  1. 创建 confirm 组件

  2. 创建一个函数组件并返回一个 promise

  3. 使用h函数生成 confirm 组件的 vnode

  4. 最后,使用 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)
}