首页 > 其他分享 >Vue3标签组件绘制--自定义按钮组件

Vue3标签组件绘制--自定义按钮组件

时间:2024-05-27 10:02:52浏览次数:15  
标签:自定义 -- border color 1px rgba 组件 type 255

不知道怎么的,突然想绘制一个标签,比如el-button什么的。

今天研究一下吧,不知道能不能整出来

以后就可以绘制自己的组件,弄自己的组件库了。不知道有朝一日能不能让越组件青史留名?

嘻嘻,百日梦做差不多了,接着去查查资料。

文章分为三个部分:

1.按钮组件实现(根据查阅的一个文章实现基础)

2.效仿el-button样式组件内容(复现type和plain功能)

最终结果:

 

看了一会儿感觉和普通的组件封装好像是差不多的原理,和平常使用的整体组件是一个道理,可能自定义上之前没有那么强。按照之前的技术能力应该也是没有问题的,这是我看的up主的内容

一.按钮组件实现

父组件:

<ice-button block color="rgb(242, 72, 27)">混合</ice-button>

子组件:

<template>
  <div class="ice-button"
       @click="clickCallBack"
       :class="[
           color?'hoverColor':'defaultColor',
           round?'round':'',
           block?'block':''
       ]"
       :style="{ '--color': color,'--hover-color': hoverColor(color) }"
  >
    <slot></slot>
  </div>
</template>

<script setup>
const props = defineProps({
  color: {
    type: String,
    default: ''
  },
  round: {
    type: Boolean,
    default: false
  },
  block: {
    type: Boolean,
    default: false
  }
})
const hoverColor = (rgb) => {
  return rgb.replaceAll(')', ',.5)')
}

const emit = defineEmits(['click'])
const clickCallBack = (evt) => {
  emit('click', evt)
}
</script>

<style scoped lang="less">
.ice-button {
  border-radius: .3rem;
  width: fit-content;
  padding: .2rem .4rem;
  margin: .1rem .2rem;
  user-select: none;
  transition-duration: .3s;
}

.defaultColor {
  border: rgba(0, 0, 0, .7) 1px solid;
  color: rgba(0, 0, 0, .7);
  transition-duration: .3s;

  &:hover {
    color: rgba(0, 0, 0, .4);
    border: rgba(0, 0, 0, .4) 1px solid;
  }
}

.hoverColor {
  color: var(--color);
  border: var(--color) 1px solid;

  &:hover {
    color: var(--hover-color);
    border: var(--hover-color) 1px solid;
  }
}

.round {
  border-radius: 2rem;
}

.block {
  border-radius: 0;
}
</style>

实现效果:

虽然说不是很好看,但是基本的方法和原理还是特别透彻了已经。

1.父组件调用组件,通过props添加样式

2.less动态修改css样式

3.条件编译减少bug

二.按钮组件样式升级

在以上的基础上我们就可以发挥下自己的小猪脑了(哦,是我的猪脑)

1.el-button中有个type属性,通过type的切换实现效果,而其中的color和round都是基本样式,我该如何实现同样的效果呢

首先肯定是在props定义一个type

  type: {
    type: String,
    default: ''
  },

修改:

<template>
  <div class="ice-button"
       @click="clickCallBack"
       :class="[
           type === 'blue' ? 'primaryColor' : '',
           type === 'danger' ? 'dangerColor' : '',
           color?'hoverColor':'',
           round?'round':'',
           block?'block':''
       ]"
       :style="{ '--color': color,'--hover-color': hoverColor(color) }"
  >
    <slot></slot>
  </div>
</template>

<script setup>
//ok
const props = defineProps({
  color: {
    type: String,
    default: ''
  },
  type: {
    type: String,
    default: ''
  },
  round: {
    type: Boolean,
    default: false
  },
  block: {
    type: Boolean,
    default: false
  }
})


const hoverColor = (rgb) => {
  return rgb.replaceAll(')', ',.5)')
}

//ok??
const emit = defineEmits(['click'])
const clickCallBack = (evt) => {
  emit('click', evt)
}
</script>

<style scoped lang="less">
.ice-button {
  border-radius: 3px;
  width: fit-content;
  padding: 2px 2px;
  margin: 1px 2px;
  user-select: none;
  transition-duration: .3s;
}

.defaultColor {
  border: rgba(0, 0, 0, .7) 1px solid;
  color: rgba(0, 0, 0, .7);
  transition-duration: .3s;

  &:hover {
    color: rgba(64, 0, 255, 0.4);
    border: rgba(64, 0, 255, 0.4) 1px solid;
  }
}

.hoverColor {
  color: var(--color);
  border: var(--color) 1px solid;

  &:hover {
    color: var(--hover-color);
    border: var(--hover-color) 1px solid;
  }
}

//ok
.round {
  border-radius: 5px;
}

//ok
.block {
  border-radius: 0;
}

.dangerColor {
  border: rgba(255, 0, 0, .7) 1px solid;
  color: rgba(255, 0, 0, .7);

  &:hover {
    color: rgba(255, 0, 0, .4);
    border: rgba(255, 0, 0, .4) 1px solid;
  }
}

.primaryColor {
  border: rgba(0, 0, 255, 0.7) 1px solid;
  color: rgba(0, 0, 255, .7);

  &:hover {
    color: rgba(0, 0, 255, .4);
    border: rgba(0, 0, 255, .4) 1px solid;
  }
}
</style>

这样就可以实现同el-button类似的感觉了(虽然好像还是有点丑)

    <ActionBtn2 round type="blue">混合</ActionBtn2>

(这边有个小内容,就是命名时使用驼峰,比如HyButton,标签名就可以使用hy-button了)

再看下el-button的

行。算你好看。这边看按钮整体可以分为这几部分

1.框色 2.字色 3.底色

default逻辑 默认框底色 字白色 悬浮降低透明度

plain逻辑 默认字框色 底白色 悬浮 字白色 底色(这是我罗里吧嗦的废话啦)

这边根据default逻辑来优化一下type样式

子组件:

定义了三个type满足三个type的情况

<template>
  <div class="ice-button"
       @click="clickCallBack"
       :class="[
           type === 'primary' ? 'primaryColor' : '',
           type === 'danger' ? 'dangerColor' : '',
           type === 'warn' ? 'warnColor' : '',
           color?'hoverColor':'',
           round?'round':'',
           block?'block':''
       ]"
       :style="{ '--color': color,'--hover-color': hoverColor(color) }"
  >
    <slot></slot>
  </div>
</template>

<script setup>
//ok
const props = defineProps({
  color: {
    type: String,
    default: ''
  },
  type: {
    type: String,
    default: ''
  },
  round: {
    type: Boolean,
    default: false
  },
  block: {
    type: Boolean,
    default: false
  }
})


const hoverColor = (rgb) => {
  return rgb.replaceAll(')', ',.5)')
}

//ok??
const emit = defineEmits(['click'])
const clickCallBack = (evt) => {
  emit('click', evt)
}
</script>

<style scoped lang="less">
.ice-button {
  width:fit-content;
  height: 30px;
  text-align: center;
  line-height: 30px;
  font-size: 16px;
  padding: 2px 20px;
  margin: 1px 2px;
  user-select: none;
  transition-duration: .3s;
  font-weight: 600;
}

.dangerColor {
  border: rgba(255, 0, 0, 1) 1px solid;
  color: rgb(255, 255, 255);
  background-color: rgba(255, 0, 0, 1);

  &:hover {
    color: rgb(255, 255, 255);
    border: rgb(255, 0, 0, .7) 1px solid;
    background-color: rgba(255, 0, 0, .7);
  }
}
.warnColor {
  border: rgb(160, 160, 0) 1px solid;
  color: rgb(255, 255, 255);
  background-color: rgba(160, 160, 0, 1);

  &:hover {
    color: rgb(255, 255, 255);
    border: rgb(160, 160, 0, .7) 1px solid;
    background-color: rgba(160, 160, 0, .7);
  }
}
.primaryColor {
  border: rgb(82, 82, 255) 1px solid;
  color: rgb(255, 255, 255);
  background-color: rgba(82, 82, 255, 1);

  &:hover {
    color: rgb(255, 255, 255);
    border: rgba(82, 82, 255, .7) 1px solid;
    background-color: rgba(82, 82, 255, .7);
  }
}

.hoverColor {
  color: var(--color);
  border: var(--color) 1px solid;
  background-color: rgba(0, 0, 0, .7);

  &:hover {
    color: var(--hover-color);
    border: var(--hover-color) 1px solid;
    background-color: rgba(0, 0, 0, .7);
  }
}

//ok
.round {
  border-radius: 10px;
}

//ok
.block {
  border-radius: 0;
}
</style>

父组件

调用3个type查看效果

import HyButton from './ActionBtn2.vue'    

<hy-button round type="primary">坏越大帅哥</hy-button>
<hy-button round type="danger">坏越大帅哥</hy-button>
<hy-button round type="warn">坏越大帅哥</hy-button>

有点那个味道了~!

这是type的设定,然后还有一个就是plain的设定,plain情况下的话,默认底色为白,框和字有色。hover时底色和框有色,字为白。这么说可能不太形象。我们可以从元素的变化来理解~

1.type情况下

文字:白色

边框:type色

底色:type色

悬浮:整体变浅

2.plain情况下

文字:type色

边框:type色

底色:白色

悬浮:文字变白,边框不动,底色变为type色

*这边要考虑到没有type的时候要给一个默认值~

由此可以看到基本所有的改变都是根据type来的,只要可以得到type,就可以简化封装~

以下为优化后的代码(可能不是最简的,这块也是第一次运用)

<template>
  <div class="ice-button"
       @click="clickCallBack"
       :class="[
           (type === 'primary'||type ==='danger'||type ==='warn') ? 'typeColor' : '',
           round ? 'round' : '',
           block ? 'block' : '',
           plain ? 'plain' :''
       ]"
       :style="{
       '--normalcolor':colors[type + 'Color'],'--hovercolors':colors[type + 'HoverColor'],
       '--plaincolor':type?colors[type + 'HoverColor']:'black','--plainhover':type?colors[type + 'Color']:'black' }"
  >
    <slot></slot>
  </div>
</template>

<script setup>
const props = defineProps({
  type: {
    type: String,
    default: ''
  },
  round: {
    type: Boolean,
    default: false
  },
  block: {
    type: Boolean,
    default: false
  },
  plain: {
    type: Boolean,
    default: false
  }
})

import { ref } from 'vue'
const colors=ref({
 dangerColor:('rgb(255, 0, 0)'),
 dangerHoverColor:('rgb(255, 0, 0, .7)'),
 warnColor:('rgb(160, 160, 0)'),
 warnHoverColor:('rgb(160, 160, 0, .7)'),
 primaryColor:('rgb(82, 82, 255)'),
 primaryHoverColor:('rgba(82, 82, 255, .7)')
})


const emit = defineEmits(['click'])

const clickCallBack = (evt) => {
  emit('click', evt)
}

</script>

<style scoped lang="less">
.ice-button {
  border-radius: 8px;
  border: 1px solid black;
  width:fit-content;
  height: 30px;
  text-align: center;
  line-height: 30px;
  font-size: 16px;
  padding: 2px 20px;
  margin: 1px 2px;
  user-select: none;
  transition-duration: .3s;
  font-weight: 600;
  &:hover {
    color: rgba(0, 0, 0,0.7);
  }
}
.typeColor {
  border: var(--normalcolor)1px solid;
  color: rgb(255, 255, 255);
  background-color: var(--normalcolor);

  &:hover {
    color: rgb(255, 255, 255);
    border: var(--hovercolors) 1px solid;
    background-color: var(--hovercolors);
  }
}

.round {
  border-radius: 20px;
}

.block {
  border-radius: 0;
}
.plain{
  background-color: rgb(255, 255, 255);
  color: var(--plaincolor);
  border: var(--plaincolor) 1px solid;

  &:hover {
    color: rgb(255, 255, 255);
    border: var(--plainhover) 1px solid;
    background-color: var(--plainhover);
  }
}
</style>

比较之前优化了type赋色的代码,通过type的赋值调用一次即可,plain也可以根据此进行自动变化。下面来看看效果

父组件:

import HyButton from './ActionBtn2.vue'   

<hy-button type="primary">坏越大帅哥</hy-button>
<hy-button block type="danger">坏越大帅哥</hy-button>
<hy-button round type="warn">坏越大帅哥</hy-button>
<hy-button type="primary" plain>坏越大帅哥</hy-button>
<hy-button block type="danger" plain>坏越大帅哥</hy-button>
<hy-button round type="warn" plain>坏越大帅哥</hy-button>
<hy-button block  plain>坏越大帅哥</hy-button>

主要运用的技能也就这两个吧:

1.less(今天也是第一次用,也是小刀拉屁股,开眼了)

2.父子通信

再加一点吧。以上都是实现和他一样,加点不一样,比如我还想加一个type-special

           type==='special'?'specialColor':'',

样式:

.specialColor {
      color: white;
      background: linear-gradient(90deg,
          #0f1ad4,
          #f528d1,
          #f736de,
          #09d3ab);
      background: linear-gradient(90deg,
          #03a9f4,
          #f441a5,
          #ffeb3b,
          #03a9f4);
      background-size: 400%;
      position: relative;
      &:hover {
      animation: animate 10s linear infinite;
      z-index:1;
      color: white;
    }

    &:before {
      content: '';
      top: -5px;
      left: -5px;
      right: -5px;
      bottom: -5px;
      position: absolute;
      background: linear-gradient(90deg,
          #03a9f4,
          #f441a5,
          #ffeb3b,
          #03a9f4);
      z-index: -1;
      opacity: 0;
      filter: blur(20px)
    }

    &:hover:before {
      opacity: 1;
    }


    }

    @keyframes animate {
      0% {
        background-position: 0 0;
      }

      100% {
        background-position: 400% 0;
      }

    }

组件运用:

    <div style="width: 100vw;height: 500px;background-color: black;display: flex;justify-content: center;align-items: center;">
        <hy-button type='special'>下次再见咯</hy-button>
    </div>

效果:

hover:

感觉还是不错的~

第一部分参考文章:手搓vue3组件_1.封装一个button_vue3封装按钮组件-CSDN博客

标签:自定义,--,border,color,1px,rgba,组件,type,255
From: https://blog.csdn.net/qq_52368602/article/details/139195696

相关文章

  • 一起学习大模型 - 从底层了解Token Embeddings的原理(2)
    文章目录前言4.TokenEmbeddings综合运用演示4.1TokenEmbeddings处理4.2伪代码示例4.3计算cat和dog两个词的相近程序4.3.1计算方法4.3.2例子4.3.3输出结果前言上一篇文章了解了TokenEmbeddings的原理,这一篇,我们一起来综合运用学到的知识来深入了解Token......
  • 【JAVA】Java如何使用Spring Boot进行Web服务开发
    文章目录前言一、函数解释二、代码实现三、总结前言在现代的微服务架构中,创建快速、可靠的Web服务已经成为一项基本技能。SpringBoot是一个出色的框架,它简化了Spring应用开发,使我们能够更快速地创建和部署Web服务。在这篇博客中,我们将探讨如何使用Java和SpringBoo......
  • 【VTKExamples::Utilities】第一期 动画模拟Animation
    很高兴在雪易的CSDN遇见你 VTK技术爱好者QQ:870202403   公众号:VTK忠粉前言本文分享VTK样例Animation,希望对各位小伙伴有所帮助!感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!你的点赞就是我的动力(^U^)ノ~YO1. Animation该样例介绍如何创建一个简单的动......
  • 探索SCSS:让CSS开发更高效的预处理器
    在现代前端开发中,CSS预处理器已成为不可或缺的工具。SCSS(SassyCSS)作为Sass的一种语法扩展,结合了Sass的强大功能和CSS的简洁语法,使得编写样式变得更加灵活和高效。本文将详细介绍SCSS的特点、使用方法以及最佳实践,帮助开发者更好地掌握这一强大的工具。一、SCSS简介SCSS是......
  • Android交叉编译
    https://www.jianshu.com/p/b31acea79717https://www.jianshu.com/p/f77554b0caef概念编译环境和运行环境不同(在一个平台(pc)生成另一个平台(Androidios等)的可执行代码)使用到的工具CC编译器对C源文件进行编译处理,生成汇编文件(CCompiler)ls-l/usr/bin/cc AS将......
  • 《从技术洞察到技术规划赋能》公开课(2024年7月12-13日)
    【课程背景】所谓技术洞察,简称(TI,TechnologyInsight),是根据市场发展趋势和客户需求,以及技术的生命周期,对某项技术发展趋势进行判断和预测,并明确未来3~5年的技术战略和战略控制点、重大的技术投资方向,完成技术战略规划的制订,并最终进行技术战略解码,为公司整体战略创造价值。技术......
  • Android热修复简易实现
    https://www.jianshu.com/p/b65e5da3dff2 先了解一下原理和实现方式Java编译为classjavacxxx.java.class打包为jar包jarcvfxxx.jarx/x/x/class#可用.来代替目录意思为当前目录和所有的子目录打包将as编译好的jar包拆开unzipa.jar-doutfilejar-xvfa.jarj......
  • 关于全局变量的坑, golang熟手们经常遇到
    关于全局变量的坑,golang熟手们经常遇到原创 fengzi Go语言圈 2024-05-2708:30 广东 听全文Go语言圈Go语言开发者的学习好助手,分享Go语言知识,技术技巧,学习与交流Go语言开发经验,互动才有助于技术的提升,每天5分钟,助你GO语言技术快乐成长160篇原创内容公......
  • ​你见过哪些不过度设计的优秀APP?​
    优联前端https://ufrontend.com/提供一站式企业前端解决方案“每日故宫”是一款以故宫博物院丰富的藏品为基础,结合日历形式展示每日精选藏品的移动应用。通过这款应用,用户可以随时随地欣赏到故宫的珍贵藏品,感受中华五千年文化的魅力。“每日故宫”在交互设计和动画视效......
  • GPS坐标转百度坐标
    坐标系类型目前国内主流坐标系类型主要有三种:WGS84、GCJ02、BD09;WGS84WGS84(WorldGeodeticSystem一1984CoordinateSystem)为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系;GCJ02GCJ02(G表示Guojia国家,C表示Cehui测绘,J表示Ju局)为国内的标准坐标体系。是......