Vue3标签组件绘制--自定义按钮组件
这是type的设定,然后还有一个就是plain的设定,plain情况下的话,默认底色为白,框和字有色。看了一会儿感觉和普通的组件封装好像是差不多的原理,和平常使用的整体组件是一个道理,可能自定义上之前没有那么强。按照之前的技术能力应该也是没有问题的,这是我看的up主的内容。1.el-button中有个type属性,通过type的切换实现效果,而其中的color和round都是基本样式,我该如何实现
不知道怎么的,突然想绘制一个标签,比如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:
感觉还是不错的~
更多推荐
所有评论(0)