element-ui 二次封装系列- button(四)(vue3版本)

2,937 阅读1分钟

前面三篇介绍了利用el-button扩充三个功能, 本文我们将三个功能合并在一起并使用vue3+element-plus来完善

<template>
  <component
    :is="content?'el-tooltip':'pl-wrapper'"
    v-bind="content?calTipConfig:{}"
  >
    <component
      :is="confirmType === 'pop'?'el-popconfirm':'pl-wrapper'"
      v-bind="confirmType === 'pop'?popConfig:{}"
      @confirm="handlePopConfirm"
      @cancel="$emit('cancel')"
    >
      <template v-slot:[slotName]>
        <el-button
          @click.stop="handleClick"
          v-loading.fullscreen.lock="fullscreenLoading"
          v-bind="$attrs"
          :loading="loading"
          :type="type">
          <slot></slot>
        </el-button>
      </template>
    </component>
  </component>
</template>

<script>
import { defineComponent, ref, computed } from 'vue'
import { ElMessageBox } from 'element-plus'
import debounce from 'lodash/debounce'

export default defineComponent({
  name: 'pl-button',
  inheritAttrs: false,
  emits: ['click', 'confirm', 'cancel'],
  props: {
    autoLoading: {
      type: Boolean,
      default: false
    },
    autoFullScreenLoading: {
      type: Boolean,
      default: false
    },
    confirmType: {
      type: String,
      default: null
    },
    confirmConfig: {
      type: Object,
      default: () => ({})
    },
    popConfig: {
      type: Object,
      default: () => ({ title: '确定删除吗?' })
    },
    type: {
      type: String,
      default: null
    },
    content: {
      type: String,
      default: null
    },
    tipConfig: {
      type: Object,
      default: null
    },
    debounce: {
      type: [Number, Boolean],
      default: false
    }
  },
  setup (props, { emit }) {
    const loading = ref(false)
    const fullscreenLoading = ref(false)
    const calTipConfig = computed(() => {
      return {
        effect: 'dark',
        placement: 'top',
        content: props.content,
        ...props.tipConfig
      }
    })
    const slotName = computed(() => {
      return props.confirmType === 'pop' ? 'reference' : 'default'
    })
    const clickDone = () => {
      loading.value = false
      fullscreenLoading.value = false
    }
    const clickStart = () => {
      if (props.autoLoading) {
        loading.value = true
      }
      if (props.autoFullScreenLoading) {
        fullscreenLoading.value = true
      }
    }
    const handleConfirm = () => {
      const {
        message = '此操作将永久删除该数据, 是否继续?',
        title = '提示',
        confirmButtonText = '确定',
        cancelButtonText = '取消',
        type = 'warning'
      } = props.confirmConfig
      ElMessageBox.confirm(message, title, {
        confirmButtonText,
        cancelButtonText,
        type
      }).then(() => {
        clickStart()
        emit('confirm', clickDone)
      }).catch(() => {
        emit('cancel')
      })
    }
    const handleClick = () => {
      if (props.confirmType === 'pop') {
        return
      }
      if (props.confirmType === 'confirm') {
        handleConfirm()
      } else {
        clickStart()
        emit('click', clickDone)
      }
    }
    const debounceTime = typeof props.debounce === 'number' ? props.debounce : 500
    const debounceClick = debounce(handleClick, debounceTime, { leading: true })
    const handlePopConfirm = () => {
      if (props.confirmType === 'confirm') {
        handleConfirm()
        return
      }
      clickStart()
      emit('confirm', clickDone)
    }
    return {
      calTipConfig,
      handleClick: props.debounce ? debounceClick : handleClick,
      handlePopConfirm,
      loading,
      fullscreenLoading,
      slotName
    }
  }
})
</script>

<style>

</style>

上述组件中,我们使用vue3+element-plusel-button扩充了一些功能,

  • 防抖
  • 自动loading
  • 全屏loading
  • popconfirm确认
  • messageBox.confirm确认
<template>
  <p>防抖按钮</p>
  <pl-button debounce @click="handleDebounceClick">防抖</pl-button>
  <p>自动loading</p>
  <pl-button auto-loading @click="handleClick">自动loading</pl-button>
  <p>自动全屏loading</p>
  <pl-button auto-full-screen-loading  @click="handleClick">全屏loading</pl-button>
  <p>popconfirm确认</p>
  <pl-button confirm-type="pop" auto-full-screen-loading @confirm="handleClick">删除</pl-button>
  <p>messageBox.confirm确认</p>
  <pl-button confirm-type="confirm" auto-full-screen-loading @confirm="handleClick">删除</pl-button>
</template>

<script>
import PlButton from '../../packages/components/button/button'
import { defineComponent } from 'vue'
import { ElMessage } from 'element-plus'

export default defineComponent({
  name: 'button-demo',
  components: { PlButton },
  setup () {
    return {
      handleDebounceClick () {
        ElMessage.success('500ms内重复点击无效')
      },
      handleClick (done) {
        setTimeout(() => {
          done()
        }, 1000)
      }
    }
  }
})
</script>

<style >

</style>

你可以通过这里来查看演示效果: www.noob6.com/pl-element3…

源码: github.com/pangao66/pl…

系列文章地址:

element-ui 二次封装系列- button(一)

element-ui 二次封装系列- button(二)

element-ui 二次封装系列- button(三)

element-ui 二次封装系列- button(四)(vue3版本)