vue3 封装一个按钮组件(可自定义按钮样式)

效果图

鼠标悬浮有对应的文字提示,且图标出现背景色和颜色

 

实现

目前提供五个固定样式的图标及三个用户自定义的图标,可根据需要补充

组件代码

<script setup lang="ts">
import { onMounted, PropType, reactive, ref, watch } from 'vue'
import Tooltip from '@/components/Tooltip/src/Tooltip.vue'
import { useI18n } from 'vue-i18n'

const { t } = useI18n()

enum BtnType {
  edit = 'edit',
  detail = 'detail',
  delete = 'delete',
  permission = 'permission',
  password = 'password',
  custom1 = 'custom1',
  custom2 = 'custom2',
  custom3 = 'custom3'
}

interface BtnAction {
  type: BtnType
  icon?: string | undefined
  color?: string | undefined
  show?: boolean | true
  tooltip?: string | undefined
  disabled?: boolean
  href?: string | undefined
}

const props = defineProps({
  actions: {
    default: () => [],
    type: Array as PropType<BtnAction[]>
  }
})
const _actions = ref(props.actions)
// 监听数据变化
watch(
  () => props.actions,
  (newVal) => {
    _actions.value = newVal
  },
  { deep: true, immediate: true }
)

const getNormalIcon = (action: BtnAction, i: number) => {
  switch (action.type) {
    case BtnType.edit:
      _actions.value[i].tooltip = t('common.edit')
      return 'svg-icon:v2-List-write_line'

    case BtnType.detail:
      _actions.value[i].tooltip = t('queueCalls.details')

      return 'svg-icon:v2-List-Contact_line'
    case BtnType.delete:
      if (!_actions.value[i].tooltip) {
        _actions.value[i].tooltip = t('common.delete')
      }
      return 'svg-icon:v2-List-delete_line'

    case BtnType.permission:
      if (!_actions.value[i].tooltip) {
        _actions.value[i].tooltip = t('manage.user.viewPermissions')
      }
      return 'svg-icon:v2-List-Authority_line'

    case BtnType.password:
      if (!_actions.value[i].tooltip) {
        _actions.value[i].tooltip = t('login.reset.ok')
      }
      return 'svg-icon:v2-List-ResetPassword_line'

    default:
      return action.icon
  }
}

const getActiveIcon = (action: BtnAction) => {
  switch (action.type) {
    case BtnType.edit:
      return 'svg-icon:v2-List-write_face'

    case BtnType.detail:
      return 'svg-icon:v2-List-Contact_face'

    case BtnType.delete:
      return 'svg-icon:v2-List-delete_face'

    case BtnType.permission:
      return 'svg-icon:v2-List-Authority_face'

    case BtnType.password:
      return 'svg-icon:v2-List-ResetPassword_face'

    default:
      return action.icon
  }
}

// 根据类型获取点击事件
const getClick = (type: BtnType) => {
  switch (type) {
    case BtnType.edit:
      return 'click:edit'
    case BtnType.detail:
      return 'click:detail'
    case BtnType.delete:
      return 'click:delete'
    case BtnType.permission:
      return 'click:permission'
    case BtnType.password:
      return 'click:password'
    case BtnType.custom1:
      return 'click:custom1'
    case BtnType.custom2:
      return 'click:custom2'
    case BtnType.custom3:
      return 'click:custom3'
    default:
      return ''
  }
}

const isCustom = (type: BtnType) => {
  return type.indexOf('custom') !== -1
}

// const disableTooltip = (action: BtnAction) => {
//   return action.tooltip === undefined || action.tooltip === ''
// }

onMounted(() => {
  // 如果show为false,移除该按钮
  // _actions.value = props.actions.filter((action) => action.show)
  // console.log('====================', _actions)
})

const emit = defineEmits([
  'click:edit',
  'click:detail',
  'click:delete',
  'click:permission',
  'click:password',
  'click:custom1',
  'click:custom2',
  'click:custom3'
])
</script>

<template>
  <div class="actions flex items-center tooltip-append">
    <div v-for="(action, i) in _actions as BtnAction[]" :key="action.type">
      <Tooltip :title="action.tooltip" :disabled="!action.tooltip">
        <v-btn
          :disabled="action.disabled === undefined ? false : action.disabled"
          v-if="action.show === undefined ? true : action.show"
          :href="action.href"
          target="_blank"
          v-bind="props"
          rounded="xl"
          class="default-btn mr-16px"
          :class="{
            'delete-btn': action.type === 'delete',
            'custom-btn': isCustom(action.type)
          }"
          @click="emit(getClick(action.type))"
          size="32"
          variant="text"
          color="#c6c8cd"
          icon
        >
          <Icon size="21" class="active-icon" :icon="getActiveIcon(action)" />
          <Icon size="21" class="normal-icon" :icon="getNormalIcon(action, i)" />
        </v-btn>
      </Tooltip>
    </div>
  </div>
</template>

<style scoped lang="scss">
.actions {
  .default-btn:hover {
    color: var(--el-color-primary) !important;
    cursor: pointer !important;
  }

  .delete-btn:hover {
    color: #db4b4b !important;
  }

  .custom-btn:hover {
    color: var(--el-color-primary) !important;
  }
}
.tooltip-append {
  .active-icon {
    display: none;
  }
  .normal-icon {
    display: block;
  }
}
.tooltip-append:hover {
  .active-icon {
    display: block;
  }
  .normal-icon {
    display: none;
  }
}
</style>

使用方法

图标数据传一个BtnAction数据格式的数组,使用默认提供的图标,只要一个type字段就可以

click事件根据对应图标类型写@click:[type]

const actions = [
  { type: 'edit' },
  {
    type: 'custom1',
    tooltip: t('common.copy'),
    icon: 'ph:copy'
  },
  {
    type: 'custom2',
    tooltip: t('common.export'),
    icon: 'svg-icon:v2-arrow_download'
  },
  { type: 'delete' }
] as any[]



<ActionBtn
  :actions="actions"
  @click:edit="editFlowTest(row)"
  @click:custom1="copyFlow(row)"
  @click:custom2="exportFlow(row)"
  @click:delete="deleteFlow(row)"
/>

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Vue官方提供的API来封装一个蓝色按钮组件,具体来说,可以创建一个名为BlueButton.vue的文件,在文件中使用template标签来定义HTML结构,style标签定义按钮样式,并使用script标签定义按钮的功能,最后导出按钮组件。 ### 回答2: Vue2是目前非常流行的前端框架之一,它提供了一种方便的方式来封装可复用的组件。下面是一个封装蓝色按钮组件的示例代码: ```html <template> <button class="blue-button"> <slot></slot> </button> </template> <script> export default { name: 'BlueButton', // 组件的props定义 props: { // 可以接受一个自定义的class class: { type: String, default: '' } }, // 组件样式 style: ` .blue-button { width: 100px; height: 40px; background-color: blue; color: white; border: none; border-radius: 4px; cursor: pointer; } ` } </script> <style scoped> /* 使用scoped属性将样式限制在当前组件中 */ .blue-button { width: 100px; height: 40px; background-color: blue; color: white; border: none; border-radius: 4px; cursor: pointer; } </style> ``` 使用示例: ```html <template> <div> <blue-button>Click Me</blue-button> </div> </template> <script> import BlueButton from './BlueButton.vue' export default { components: { BlueButton } } </script> ``` 这样就可以在Vue项目中使用`<blue-button></blue-button>`来渲染一个蓝色的按钮,并且按钮的文本内容可以自定义按钮样式也可以进一步自定义,通过传入一个自定义的class来覆盖默认样式。 ### 回答3: Vue一个流行的JavaScript框架,用于构建用户界面。通过Vue组件化系统,我们可以封装可重用的蓝色按钮组件。 首先,我们需要创建一个Vue组件。我们可以使用Vue的单文件组件(.vue)来封装我们的按钮组件。 在.vue文件中,我们可以定义模板、样式和逻辑。以下是一个示例蓝色按钮组件的代码: ```html <template> <button class="blue-button" @click="handleClick"> {{ buttonText }} </button> </template> <script> export default { props: { buttonText: { type: String, default: 'Click me' // 默认按钮文本 } }, methods: { handleClick() { // 处理按钮点击事件 console.log('Button clicked'); } } } </script> <style scoped> .blue-button { background-color: blue; color: white; border: none; padding: 10px 20px; cursor: pointer; } </style> ``` 在上述示例中,我们定义了一个名为`blue-button`的按钮组件。该组件接受一个`buttonText`属性,用于设置按钮的文本。当按钮被点击时,将触发`handleClick`方法,控制台将输出“Button clicked”。我们还为按钮应用了一些样式,使其具有蓝色的背景和白色的文本。 要在应用中使用我们的蓝色按钮组件,需要在父组件中导入它,并在模板中使用它。以下是一个使用示例: ```html <template> <div> <blue-button buttonText="Click me"></blue-button> </div> </template> <script> import BlueButton from './BlueButton.vue'; export default { components: { BlueButton } } </script> ``` 在上述示例中,我们将蓝色按钮组件引入为`BlueButton`,然后在模板中使用它,将`buttonText`属性设置为“Click me”。 这样,我们就成功封装一个蓝色按钮组件,并在应用中使用它。无论我们需要在应用的哪个地方使用蓝色按钮,只需要简单地将`<blue-button>`标签添加到模板中即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值