这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
前言👋
- 用户就是上帝,站在上帝的角度也就是站在使用者的角度去看待组件。
- 用过不少优秀的
UI库,用的时候美滋滋,轮到自己搭组件库的时候往往会去参考别人的源码。 - 看完源码后恍然大悟 噢!原来可以这样写,但心里难免会有疑惑别人是怎么想出来这种解决思路的?🤳
- 这一系列文章主要是面向未理解或者有疑惑的同学所以讲的比较基础,就让我们站在用户的角度去思考结构,看看换一种思路去写代码是不是有变化?
关于Rate组件⭐
为什么我们会用到Rate
作为用户👨💼
- 前面也说了很多次,用户更加注重的是视觉上的冲击主要以方便为主,试想要给一个产品或者美食评分你会选择手输入
90100分还是希望有个东西可以点击选择,我想大部分都会选择第二种。 - 所以现在不管是移动端还是pc端,现在越来越多的评分按钮出现在我们的眼前,不仅是为了美观还有的是满足我们的
懒人心理
作为组件库使用者👨💻
- 我们可以看到很多的组件库都有
Rate,Rate翻译成中文是比率,等级的意思。 - 当我们将组件库的
Rate组件放到我们的页面我们想要的效果是什么?- 有亮丽的颜色对比
- 可以满足基本的选择需求
- 可以用百分比来展示所选的评分(比如:
半星小数点评分) - 可以在基本的需求上进行定制增加功能(比如:
颜色属性禁用是否添加文字)
- 在某一个方面来说,
Rate的出现也让我们在制作页面时给了用户除了选择下拉框,开关之外有其他的选择,说白了就是让页面更加鲜艳了不会那么单调。
搭建组件⚒️
接下来可能用尽可能少的代码搭配
element的源码进行结构说明,配合element Rate源码食用更加美味喔
基本架子🔨
- 要设计一个上图这种的
Rate不难,我们会需要五个容器假设为空,当我们鼠标经过后会填充,当我们鼠标选择后他会停留最后一次所有选择填充的容器数,当我们鼠标离开后他会回到最初点击前的状态。 - 总结起来总共也只有
4个要点- 准备一个外部的五个初始元素
- 准备一个鼠标触摸事件、鼠标点击事件和一个鼠标离开容器的事件
- 各种事件呈现的效果顺带加上亿点点的过渡效果
- 双向绑定组件外的值和子组件的值
<template>
<div class="zl-rate">
<span
v-for="(item, key) in max"
:key="key"
class="zl-rate__item"
>
<i class="zl-icon-aixin_shixin"></i>
</span>
</div>
</template>
- 以上就是
element最简单的rate结构,可以看到子组件接受一个max来控制图标个数,再将span遍历即可,这里我用v-model传了一个value,具体怎么使用我会在下面解释,这里我个人的组件用了个人的爱心图标~❤️具体样式可以看element 样式 - 当然这只是一个架子我们还需要加上触摸事件和点击事件让他填充起来
设置事件🧨
- 填充其实就是改变了颜色,首先我们准备两个颜色一个代表空一个代表填充
- 因为我们的爱心是通过遍历而形成的我们可以鼠标移动到该元素就可以用
currentValue记录下来该元素的item,当currentValue大于等于item时那么就说明我们已经经过了这个爱心所以他应该是填充的颜色,通过这个思路可以动态切换我们的颜色样式 - 在设置一个鼠标移出事件当我们鼠标移出爱心时就清空所有回到最初的状态,这里清空的时候让
currentValue回归到外部传进来的value值,而这个value值是怎么来的呢相信看过我之前两篇文章的同学已经很熟悉就是v-model的语法糖自动生成的。
template
...
<span
v-for="(item, key) in max"
:key="key"
class="zl-rate__item"
@mousemove="setCurrentValue(item, $event)"
@mouseleave="resetCurrentValue"
>
<i
class="zl-icon-aixin_shixin "
:class="[{ 'hover': hoverIndex === item }]"
:style="getIconStyle(item)"
></i>
</span>
...
script
...
props:{
value: {
type: Number,
default: 0
},
max: {
type: Number,
default: 5
},
},
data(){
return{
currentValue:0,
hoverIndex: -1,
voidColor:'#C6D1DE',
activeColor:'red'
};
},
methods:{
setCurrentValue(value) {
this.currentValue = value;
this.hoverIndex = value;
},
resetCurrentValue() {
//清空颜色
this.currentValue = this.value;
this.hoverIndex = -1;
},
getIconStyle(item) {
const voidColor = this.voidColor;//默认颜色(即空的颜色)
return {
//是否小于选中的值,是则填充颜色否则则为默认
color: item <= this.currentValue ? this.activeColor : voidColor
};
}
}
...
双向绑定🎶
- 现在我们的爱心可以随着鼠标移动和移出来控制样式了
- 但是单单只是颜色变换可不行,我们需要记录下来点击后的数值,这时候就需要用到外面的
v-model了 - 在父组件我们用
v-model传入了一个值, 而v-model的语法糖会把这个值当成props的value传到子组件,子组件只要通过$emit时间改变外部的input事件就可以啦。
···
<span
v-for="(item, key) in max"
:key="key"
class="zl-rate__item"
@mousemove="setCurrentValue(item, $event)"
@mouseleave="resetCurrentValue"
@click="selectValue(item)"
>
<i
class="zl-icon-aixin_shixin "
:class="[{ 'hover': hoverIndex === item }]"
:style="getIconStyle(item)"
></i>
</span>
···
···
selectValue(value) {
this.$emit('input', value);
},
···
- 在这里我们增加一个鼠标点击事件,这样我们点击爱心时就会记录当前的value传到父组件,父组件就可以根据这个值来做一些逻辑,内部的子组件因为鼠标移出事件使子组件的
currentValue自动接收了外部的value让爱心在视觉上是填满了的。 - 这样一来我们的一个最简单的
rate就做好了。
更多需求🧮
- 一个最简单的架子搭好了接下来就可以定制我们的组件了。
- 比如说禁用啊,加文字啊,相信大家也已经很熟悉了,无非就是通过插槽获取通过
props实现动态样式切换即可。 - 当然
element的Rate也做了半星等操作,这次的组件结构就分享到这里啦,更多的实现可以参考传送门进行学习~
写在最后👋
- 总的来说
Rate组件相对于其他复杂组件比较简单,难点在于如何控制半星等样式操作。 - 对于组件库的搭建我也在慢慢的摸索,讲的都是我自己得出来的分享所以说可能对于大佬来说会比较基础,但我相信我的不断输出可以帮助到一些有疑惑的同学。
- 如果您觉得这篇文章有帮助到您的的话不妨🍉关注+点赞+收藏+评论+转发🍉支持一下哟~~😛