index.vue 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. <template>
  2. <div ref="iconfontRef" :class="['app-iconfont', active && 'is-active']">
  3. <span :class="iconClass" :style="iconStyles"></span>
  4. <span class="app-iconfont__label" v-if="label || $slots.default">
  5. <slot>{{ label }}</slot>
  6. </span>
  7. </div>
  8. </template>
  9. <script lang="ts" setup>
  10. import { shallowRef, computed, PropType, onMounted } from 'vue'
  11. const props = defineProps({
  12. icon: {
  13. type: String,
  14. required: true
  15. },
  16. color: String,
  17. size: String,
  18. active: Boolean,
  19. activeIcon: String,
  20. activeColor: String,
  21. label: String,
  22. // 标签方向
  23. labelDirection: {
  24. type: String as PropType<'left' | 'right' | 'top' | 'bottom'>,
  25. default: 'right',
  26. },
  27. })
  28. const iconfontRef = shallowRef<HTMLDivElement>()
  29. const iconClass = computed(() => {
  30. const classList = ['g-icon']
  31. if (props.active) {
  32. classList.push(props.activeIcon ?? props.icon)
  33. } else {
  34. classList.push(props.icon)
  35. }
  36. return classList
  37. })
  38. const iconStyles = computed(() => ({
  39. fontSize: props.size,
  40. color: props.activeColor ?? props.color
  41. }))
  42. onMounted(() => {
  43. const el = iconfontRef.value
  44. if (el) {
  45. switch (props.labelDirection) {
  46. case 'left': {
  47. el.style.setProperty('flex-direction', 'row-reverse')
  48. break
  49. }
  50. case 'top': {
  51. el.style.setProperty('flex-direction', 'column-reverse')
  52. break
  53. }
  54. case 'bottom': {
  55. el.style.setProperty('flex-direction', 'column')
  56. break
  57. }
  58. }
  59. }
  60. })
  61. </script>
  62. <style lang="less">
  63. @import './index.less';
  64. </style>