极简封装:基于vue3 封装 iOS UIButton 等价组件 VButton

209 阅读1分钟

需求中大量用到点击按钮进行多种状态转换的场景,顺手封装为组件 VButton.

  1. 默认样式:圆角矩形,主题色字体边框;(不可点击态 opacity: 0.4);

  2. 高亮样式:圆角矩形,白色字体,主题色背景;(不可点击态 opacity: 0.4);

  3. 可通过 classHighlighted 动态传入类名,自定义高亮样式);

  4. 效果图 截屏2022-07-02 11.16.57.png

  5. 使用示例

<template>
  <div>
    <VButton 
      class="VButton" 
      @click="click"
    >默认样式
    </VButton>

    <VButton 
      class="VButton" 
      type="highlighted" 
      @click="click"
    >高亮样式
    </VButton>

    <VButton 
      class="VButton" 
      color="red" 
      @click="click"
    >红色默认
    </VButton>
    <VButton
      class="VButton"
      color="red"
      type="highlighted"
      @click="click"
    >红色高亮
    </VButton>

    <VButton 
      class="VButton" 
      disabled 
      @click="click"
    >默认不可点击态
    </VButton>

    <VButton 
      class="VButton" 
      type="highlighted" 
      disabled 
      @click="click"
    >高亮不可点击态
    </VButton>


    <VButton
      class="VButton"
      color="red"
      type="highlighted"
      classHighlighted="Highlightedone"
      @click="click"
    >自定义高亮样式
    </VButton>

    <VButton
      class="VButton"
      :isHighlighted="isHighlighted"
      @click="click"
    >
      点击切换样式
    </VButton>

  </div>
</template>

<script setup>
import {ref, reactive, onMounted, watch} from "vue";

let isHighlighted = ref(false)


const click = (e) => {
  console.log(">>>", e.target);
  isHighlighted.value = !isHighlighted.value;
};
</script>

<style scoped lang="scss">

.VButton {
  margin: 8px;
  padding: 3px 5px;
}
// .VButton:hover{
//   color: green;
//   border: 1px solid green;
// }

.Highlightedone {
  color: blue;
  background: seagreen;
}

</style>

</style>


  1. VButton.vue
 /**
  支持两种 type: 
  默认(normal): 白色背景,外边框圆角矩形;
  高亮(highlighted): 可设置背景,字体颜色;
  通过 disabled控制按钮是否可以点击态;
*/


<template>
  <button 
    :class="['button', type, classHighlighted, isHighlighted ? 'highlighted' : '', disabled ? 'disabled' : '']"
  >
    <slot>{{ title }}</slot>
  </button>
</template>

<script setup>

const props = defineProps({
  title: {
    type: String,
    default: "VButton",
    validator: (value) => {
      return value;
    }
  },
  type: {
    type: String,
    default: "normal",
    validator: (value) => {
      return ["normal", 'highlighted'].includes(value);
    }
  },
  color: {
    type: String,
    default: "#BE965A",
    validator: (value) => {
      return value;
    }
  },
  classHighlighted: {
    type: String,
    default: "",
  },
  isHighlighted: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
});

</script>

<style scoped lang="scss">
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin line-limit-length {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@mixin text {
  font-family: PingFangSC-Regular;
  font-size: 12px;
  color: #333333;
  letter-spacing: 0;
  line-height: 16px;
}
.button {
  @include flex-center;
  @include text;
  @include line-limit-length;

  color: v-bind(color);
  background: v-bind(bg);

  border: 1px solid v-bind(color);
  border-radius: 4px;
}
.highlighted {
  color: #ffffff;
  background: v-bind(color);
  border: 1px solid transparent;
}
.disabled {
  opacity: 0.4; //有选择图片的弹窗时,会图层错位
}
</style>

VButtonDemo