前言
相信我们做前端的都有一个特别头疼的问题,就是如何给html标签定义css名称而且又要防止样式冲突,并且在写样式的时候,存在很多重复性的样式,比如margin,padding,font-size,color等等,我最近就在想一个问题,怎样才能更高效的将页面进行布局并具有高效的可维护性,并且如果将此套代码集成到其他新项目,是否可以快速使用呢?Less提供的函数可以帮助我们快速定义一些常用的class,话不多说,开干!
Less
Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性,使 CSS 更易维护和扩展。
Less 可以运行在 Node 或浏览器端。
具体的文档可以访问less官网查阅。
思路梳理
颜色
可以发现,很多ui组件库都会提供5种行为相关的颜色:primary(主题),success(成功),info(通知),warning(警告),error(错误)。同样我们可以参考这种模式定义变量:
//variable.less:定义变量文件
/* 行为相关颜色 */
@color-primary: #4897ff;
@color-success: #4cd964;
@color-info:#007aff;
@color-warning: #f0ad4e;
@color-error: #dd524d;
//定义下面两个变量的意义在于方便遍历处理,接下来就知道用途所在;
//因为less变量不支持定义对象形式,所以需要将key和value单独定义,一一对应即可;
@list:primary,success,info,warning,error;//颜色列表key
@colors:@color-primary,@color-success,@color-info,@color-warning,@color-error;//颜色列表value
定义变量之后,我们就可以根据自己的需求去定义一些常用的class:
下面会用到less的一些语法,具体的使用可以访问官网:
-
循环Loops
示例:
.generate-columns(@n, @i: 1) when (@i =< @n) { .column-@{i} { width: (@i * 100% / @n); } .generate-columns(@n, (@i + 1)); } .generate-columns(4);输出结果:
.column-1 { width: 25%; } .column-2 { width: 50%; } .column-3 { width: 75%; } .column-4 { width: 100%; } -
选取extract
实例:
@list: apple, pear, coconut, orange; value: extract(@list, 3);输出结果:
value: coconut; -
长度length
实例:
@list: "banana", "tomato", "potato", "peach"; n: length(@list);输出结果:
n:4 -
颜色操作darken/lighten

//color.less:颜色文件
@import './variable.less';//上个定义变量的文件
// 生成主题字体颜色方法
.create-color(@lt,@i:1,@key:extract(@lt, @i),@val:extract(@colors,@i)) when (length(@lt)>=@i){
.color-@{key}{
color : @val;
}
.create-color(@lt, @i + 1);
}
.create-color(@list);
为了方便测试,可以使用lessc工具(npm i less -g),编译less为css(如果项目中有less环境,则会自动编译无需此步骤):
lessc color.less > color.css
输出结果:
.color-primary {
color: #4897ff;
}
.color-success {
color: #4cd964;
}
.color-info {
color: #007aff;
}
.color-warning {
color: #f0ad4e;
}
.color-error {
color: #dd524d;
}
通过上面的方式,我们可以很方便定义一些常用的class,当在html标签中需要使用时,直接加入到classname就可以,也无需考虑命名的问题;当然还有很多其他的class也需要定义,比如字体,间距(padding ,margin)等,方式是同理的;
padding
我以padding举个例子:间距的方式可以考虑size的形式来命名:xs,sm,base,lg,xl等,当然如果你有其他的可以继续添加;
//variable.less
/* 间距 */
@spacing-base: 20px;
@spacing-xs: @spacing-base - 15px;//5px
@spacing-sm: @spacing-base - 10px;//10px
@spacing-lg: @spacing-base + 10px;//30px
@spacing-xl: @spacing-base + 20px;//40px
@size:xs,sm,base,lg,xl;
@spacings:@spacing-xs,@spacing-sm,@spacing-base,@spacing-lg,@spacing-xl;
定义间距的函数来生成class
//spacing.less
@import './variable.less';
//padding==================
// 生成间距方法
.create-padding(@lt,@i:1,@key:extract(@lt, @i),@val:extract(@spacings,@i)) when (length(@lt)>=@i){
.padding-@{key}{
padding : @val;
}
.create-padding(@lt, @i + 1);
}
.create-padding(@size);
编译输出结果:
.padding-xs {
padding: 5px;
}
.padding-sm {
padding: 10px;
}
.padding-base {
padding: 20px;
}
.padding-lg {
padding: 30px;
}
.padding-xl {
padding: 40px;
}
除了padding,margin,font-size,border-radius等都可以使用size的形式来定义,方法是一样的;
总结
程序员一定要学会越来越‘懒’,重复性的工作坚决不做,所以我们就要去学习和探索如何才能做到‘懒’到极致,就像我们写style一样,我们会发现padding,margin,text-align,display,font-size,color,background-color等会在每个页面甚至每个标签都会不断的重复,不仅写的很烦,而且还特别降低效率,这样我们就需要去寻找属于我们自己偷懒的方法;当然这些class只是一部分,后续我会将我定义好的less文件提供给大家下载,希望大家能指出存在的问题以及有没有更好的建议。
后续
文件名定义
通过需要的功能点来定义常用的class,方便按需引入和定位查找;

--border.less //边框,圆角等;
--color.less //字体颜色,背景色等;
--font.less //字体样式,大小,字体,粗细等;
--form.less //表单样式,input,textarea等;
--icon.less //字体图标以及样式;
--main.less //将所有的less文件全部引入,即全局引入;
--position.less //位置样式,display,text-align,position,flex等
--reset.less //解决浏览器兼容性问题和一些系统默认样式重置
--size.less //尺寸,width,height等
--spacing.less //间距,margin,padding等
--transition.less //动画
--variable.less //所有的变量
举个栗子:
1、按钮
<h2>按钮</h2>
<div class="padding-l-base">
<h3>行为颜色</h3>
<div class="padding-l-base">
<button class='bgcolor-primary highlight me-button'>primary</button>
<button class='bgcolor-success highlight me-button'>success</button>
<button class='bgcolor-info highlight me-button'>info</button>
<button class='bgcolor-warning highlight me-button'>warning</button>
<button class='bgcolor-error highlight me-button'>error</button>
</div>
<h3>行为颜色渐变</h3>
<div class="padding-l-base">
<button class='linear-g-primary highlight me-button'>primary</button>
<button class='linear-g-success highlight me-button'>success</button>
<button class='linear-g-info highlight me-button'>info</button>
<button class='linear-g-warning highlight me-button'>warning</button>
<button class='linear-g-error highlight me-button'>error</button>
</div>
<h3>不同尺寸</h3>
<div class="padding-l-base">
<button class='linear-g-primary highlight me-button small'>小28px</button>
<button class='linear-g-primary highlight me-button'>默认34px</button>
<button class='linear-g-primary highlight me-button large'>大40px</button>
</div>
<h3>镂空</h3>
<div class="padding-l-base">
<button class='me-button bgcolor-inverse highlight color-primary border-primary'>primary</button>
<button class='me-button bgcolor-inverse highlight color-success border-success'>success</button>
<button class='me-button bgcolor-inverse highlight color-info border-info'>info</button>
<button class='me-button bgcolor-inverse highlight color-warning border-warning'>warning</button>
<button class='me-button bgcolor-inverse highlight color-error border-error'>error</button>
<button class='me-button bgcolor-inverse highlight text-c-pri border-base'>inverse</button>
</div>
</div>
结果:

补充:可能有些人会说这个看起来一堆的class,代码编写起来可能会更加繁琐并且没有效率;其实不然,我们的很多需要复用的组件,都是要单独封装的,这样,我们维护起来,你会发现,会更方便并且更容易维护,而且定义的这些公用样式,还可以给其他标签使用,例如我就定义一个button
<template>
<button
class='me-button'
:class="[
(gradient&&!disabled)?'linear-g-'+color:(inverse?'bgcolor-inverse':'bgcolor-'+color),
(inverse&&!disabled)?('color-'+color+' border-'+color):'',
disabled?'bg-c-dis':(loadingShow?'me-loading':'highlight'),
size
]" @click='buttonClick'>
<i v-show='loadingShow' class="meiconfont meicon-loading margin-r-xs"></i>
<span>
<span v-if='!$slots.default'>buttonName</span>
<slot></slot>
</span>
</button>
</template>
<script>
export default {
name:'meButton',
props:{
//是否加载
'loading':{
type:Boolean,
default:false
},
//延迟时间
'duration':{
type:Number,
default:2
},
//是否渐变
'gradient':{
type:Boolean,
default:false
},
//颜色主题
'color':{
default:'primary'
},
//是否镂空
inverse:{
type:Boolean,
default:false
},
//大小尺寸
'size':{
type:String,
default:''
},
//是否禁用
'disabled':{
type:Boolean,
default:false
},
//是否延迟
'timeout':{
type:Boolean,
default:true
}
},
watch:{
loading:{
handler:function(n,o){
if(!n){
clearTimeout(this.clickTimer)
this.clicked = false
clearTimeout(this.loadingTimer)
this.loadingShow = false
}else{
this.loadingTimer =setTimeout(() => {
this.loadingShow = true
}, 1000);
}
}
}
},
data () {
return {
clicked:false,
clickTimer:null,
loadingShow:false,
loadingTimer:null
};
},
methods: {
buttonClick(e){
if(this.clicked || this.disabled) return
this.$emit('click',e)
if(this.isTimeout){
this.clicked = true
this.clickTimer = setTimeout(()=>{
this.clicked = false
},this.duration*1000)
}
}
}
}
</script>
然后,我们就可以这样使用:
<template>
<div class="padding-base bg-c-inv margin-b-base">
<h3>行为颜色</h3>
<div class="padding-l-base">
<me-button v-for="item in lists" :key='item' :color='item' class='margin-r-xs'>{{item}}</me-button>
<me-button :disabled='true'>disabled</me-button>
</div>
<h3>行为颜色渐变</h3>
<div class="padding-l-base">
<me-button v-for="item in lists" :key='item' :color='item' :gradient='true' class='margin-r-xs'>{{item}}</me-button>
</div>
<h3>不同尺寸</h3>
<div class="padding-l-base">
<me-button v-for="item in sizes" :key='item.size' color='primary':gradient='true' :size='item.size' class='margin-r-xs'>{{item.name}}</me-button>
</div>
<h3>镂空</h3>
<div class="padding-l-base">
<me-button v-for="item in lists" :key='item' :color='item' :inverse='true' class='margin-r-xs'>{{item}}</me-button>
<button class='me-button bgcolor-inverse highlight text-c-pri border-base'>inverse</button>
</div>
<h3>带Loading效果</h3>
<div class="padding-l-base">
<me-button :loading='btnLoading' @click='changebtnLoading'>点击加载loading</me-button>
</div>
</div>
</template>
<script>
export default {
data(){
return {
lists:[
'primary',
'success',
'info',
'warning',
'error'
],
btnLoading:false,
sizes:[
{size:'small',name:'small 28px'},
{size:'',name:'normal 34px'},
{size:'large',name:'large 40px'},
],
}
}
}
</script>
github
项目已经更新到github上,点击me-project进行跳转,感兴趣的码友可以下载下来尝试一下,我只是个工作一年多的菜鸟,代码很low希望大家多多包涵,有问题或者其他好的建议可以提出来,沟通交流才是前进最大的垫脚石。