项目更迭创建前端ui组件库的一些归纳总结。
1.组件化开发解决的问题:
- 复用代码降低耦合性,不同模块相同功能表现一致,使代码阅读清晰,减少重复工作,降低开发成本。
2.组件化开发原则:
-
耦合性:减少依赖和业务属性,数据要求通用,一个组件专注一件事。
-
可配置:明确输入配置和输出结果,输入配置包括数据,样式,配置代码,事件回调等,输出结果是响应式的
-
标准性:遵守约定俗成和系统统一标准,能被不同开发人员简单使用。
-
复用性:可作用于不同场景,不拘泥于特定业务
注释: 如果与业务强关联的组件应根据不同业务场景切割组件,组件过于粗糙则开发低效解耦失败,组件粒度过细则增强了数据控制难度,调用难度 。
3.实例(可拖拽进度条组件)
实际效果:
可拖拽进度条组件参数:
入参 | 描述 |
---|---|
min | 进度调左侧对应最小值 |
max | 进度条右侧对应最大值 |
value | 当前值 |
color | 进度条颜色 |
renderSign | 是否重绘进度条 |
代码:
<template>
<div ref="slider" class="common-slider-style">
<div class="process" :style="{ width, background: color }"></div>
<div class="thunk" ref="trunk" :style="{ left }">
<span class="thunk-number">{{ scale * 10 }}</span>
</div>
<span class="process-min">{{ min }}</span>
<span class="process-max">{{ max }}</span>
</div>
</template>
<script>
/*
* min 进度条最小值
* max 进度条最大值
* v-model 对当前值进行双向绑定实时显示拖拽进度
* */
export default {
props: ['min', 'max', 'value', 'color', 'renderSign'],
data () {
return {
slider: null, //滚动条DOM元素
thunk: null, //拖拽DOM元素
per: this.value //当前值
}
},
//渲染到页面的时候
mounted () {
this.init()
},
watch: {
renderSign () {
console.log(
'value change currentval is : ' +
this.per +
' this.value:' +
this.value
)
this.per = this.value
this.init()
}
},
computed: {
// 设置一个百分比,提供计算slider进度宽度和trunk的left值
// 对应公式为 当前值-最小值/最大值-最小值 = slider进度width / slider总width
// trunk left = slider进度width + trunk宽度/2
scale () {
return (this.per - this.min) / (this.max - this.min)
},
width () {
if (this.slider) {
return this.slider.offsetWidth * this.scale + 'px'
} else {
return 0 + 'px'
}
},
left () {
if (this.slider) {
return (
this.slider.offsetWidth * this.scale -
this.thunk.offsetWidth / 2 +
'px'
)
} else {
return 0 + 'px'
}
}
// per(){
// return this.value
// }
},
methods: {
init () {
this.slider = this.$refs.slider
this.thunk = this.$refs.trunk
var _this = this
this.thunk.onmousedown = function (e) {
var width = parseInt(_this.width)
var disX = e.clientX
document.onmousemove = function (e) {
// value, left, width
// 当value变化的时候,会通过计算属性修改left,width
// 拖拽的时候获取的新width
var newWidth = e.clientX - disX + width
// 拖拽的时候得到新的百分比
var scale = newWidth / _this.slider.offsetWidth
_this.per = Math.ceil((_this.max - _this.min) * scale + _this.min)
_this.per = Math.max(_this.per, _this.min)
_this.per = Math.min(_this.per, _this.max)
_this.$emit('input', _this.per)
}
document.onmouseup = function () {
document.onmousemove = document.onmouseup = null
}
return false
}
}
}
}
</script>
<style>
.box {
margin: 100px auto 0;
width: 80%;
}
.clear:after {
content: '';
display: block;
clear: both;
}
.slider {
position: relative;
margin: 20px 0;
width: 200px;
height: 10px;
background: #e4e7ed;
border-radius: 5px;
cursor: pointer;
}
.slider .process {
position: absolute;
left: 0;
top: 0;
width: 112px;
height: 10px;
border-radius: 5px;
background: #409eff;
}
.slider .thunk {
position: absolute;
left: 100px;
top: -7px;
width: 20px;
height: 20px;
}
.slider .block {
width: 20px;
height: 20px;
border-radius: 50%;
border: 2px solid #409eff;
background: rgba(255, 255, 255, 1);
transition: 0.2s all;
}
.slider .tips {
position: absolute;
left: -7px;
bottom: 30px;
min-width: 15px;
text-align: center;
padding: 4px 8px;
background: #000;
border-radius: 5px;
height: 24px;
color: #fff;
}
.slider .tips i {
position: absolute;
margin-left: -5px;
left: 50%;
bottom: -9px;
font-size: 16px;
color: #000;
}
.slider .block:hover {
transform: scale(1.1);
opacity: 0.6;
}
</style>