博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何编写通用的 Helper Class
阅读量:7021 次
发布时间:2019-06-28

本文共 7931 字,大约阅读时间需要 26 分钟。

Github:

Docs:

前言

什么是 helper ?任何框架都不是万能的,而业务需求却是多种多样,很多时候我们只需要更改组件的部分属性,而 helper 就是调整细节的工具。我在之前的文章《》中也举过例子,我们完全没必要因为几个属性的不同而重新编写新组件。大部分的 helper 都是一个类对应一个 CSS 属性,属于最细小的类。通过工作的实践总结,我觉得编写一套简单易用、通俗易懂的 helper 非常重要。本文的目的就是探讨 helper 的组成部分、编写方式以及如何精简 helper 的命名。

组件与零件

详细介绍如何编写 helper 之前,先说一下我对于组件以及零件的看法。在之前编写轻量级 CSS 框架的时候,我们是以组件的方式开发。而编写 helper 更像是开发一个零件,因为 helper 的属性单一,而且多个 helper 可以形成一个组件。比如下面的例子:

假设有 .boxes 组件

.boxes {    border: 1px solid #eee;    border-radius: 5px;    margin-bottom: 15px;    overflow: hidden;}复制代码

假设有如下 helper

.b-1 {    border: 1px solid #eee !important;}.r-5{    border-radius: 5px !important;}.m-b-15{    margin-bottom: 15px !important;}.overflow-hidden {    overflow: hidden !important;}复制代码

.boxes = .b-1 + .r-5 + .m-b-15 + .overflow-hidden

我是一个模型爱好者,这样的组合方式让我想到了寿屋的 ,这个系列的特点是“零件+零件=组件、组件+组件=骨架、骨架+骨架=素体、素体+武装=机体”。

在编写 helper 的时候,基于以上想法,我在思考是否可以把 helper 拆分的足够精细,这样它就可以自成一体形成一个框架,也就是“零件+零件=组件、组件+组件=框架”。令人遗憾的是,我的想法已经被人实践,前几天浏览 GitHub 时发现了相关的项目 ,这个框架就是以 helper 为基础,通过属性叠加的方式添加样式。

组件式框架和零件式框架是两种完全不同的思想,难分伯仲,各有优缺点。

Helper 的组成部分

一套完整的 helper 应该包含哪些内容呢?一般常用的有 paddingmarginfont-sizefont-weight 等。为了编写更为通用的 helper,我们需要更细致的划分。虽然我们并没有打算把它写成一个框架,但是我们希望 helper 的功能足够强大。通过对比和思考,我将 helper 暂时划分成以下几个模块:

  • Colors(颜色,包括 bg-color 及 text-color)
  • Paddings(内边距序列)
  • Margins(外边距序列)
  • Typography(排版,包括 font-size 及 font-weight)
  • Border(边框线)
  • Radius(圆角)
  • Shadow(阴影)
  • Size(尺寸,包括 height 及 width)
  • Gutters(栅格间距序列)
  • Alignment(主要是 vertical-align)
  • ...

和之前编写轻量级框架一样,我们同样使用 Sass 预编译器。helper 类几乎都是 Sass 循环生成的,所以源代码看上去很精简。

颜色变量

因为颜色稍微特殊一点,我将颜色与其它内容分开单独介绍。在编写轻量级框架的时候,我也定义了常用的一些颜色,但是面对特殊需求时略显单一,所以我们需要使用 helper 扩充颜色集群。但是颜色是一个无法量化的概念,所以再强大的 helper 也无法面面俱到,只能是一定程度上的补充。参考常用的颜色值,最终我设置了红、橙、黄、绿、青、蓝、靛、紫、粉、冷灰、暖灰等几种色系。

其中每个颜色都有六个亮度值,分别用 -lightest-lighter-light-dark-darker-darkest 表示,此处有参考 tailwindcss 的颜色命名。这些颜色都是通过 Sass 的颜色函数生成的。以灰色为例,Sass 代码如下:

$gray:#999;$gray-light:lighten($gray, 15%);$gray-lighter:lighten($gray, 25%);$gray-lightest:lighten($gray, 35%);$gray-dark:darken($gray, 15%);$gray-darker:darken($gray, 25%);$gray-darkest:darken($gray, 35%);复制代码

这些颜色序列看上去很像一套马克笔,不过马克笔灰色系更丰富,包括冷灰、暖灰、蓝灰、绿灰。

其中背景色的循环方式如下,为了便于循环,我们定义了一个 color map,然后用 @each 方法循环。

$color-list:(    'gray':$gray,    'brown':$brown,    'red':$red,    'orange':$orange,    'yellow':$yellow,    'green':$green,    'teal':$teal,    'blue':$blue,    'indigo':$indigo,    'purple':$purple,    'pink':$pink);@each $name,$color in $color-list {    .bg-#{
$name} { background-color: $color; } .bg-#{
$name}-light { background-color: lighten($color, 15%); } .bg-#{
$name}-lighter { background-color: lighten($color, 25%); } .bg-#{
$name}-lightest { background-color: lighten($color, 35%); } .bg-#{
$name}-dark { background-color: darken($color, 15%); } .bg-#{
$name}-darker { background-color: darken($color, 25%); } .bg-#{
$name}-darkest { background-color: darken($color, 35%); }}复制代码

命名策略

理所当然,我又提到了命名策略。在编写轻量级框架的时候,我也着重讨论了类命名策略以及比较了一些框架的命名方式。无论是框架还是 helper,类命名都决定了其易用性,而且会影响使用者的习惯,所以我会从简洁、直观、易用等几个角度命名。不过 helper 的命名比较简单,因为几乎大多数都是单一的 CSS 样式,所以命名策略基本都是对 CSS 属性的抽象与简化。

数字型命名 VS. 尺寸型命名

我在工作中接触过两种 helper 序列的表示方法,一种是常见的数字型,另一种是尺寸型。以 padding 为例:

数字型

.p-5 {  padding: 5px !important;}.p-10 {  padding: 10px !important;}.p-15 {  padding: 15px !important;}.p-20 {  padding: 20px !important;}.p-25 {  padding: 25px !important;}复制代码

尺寸型

.p-xs {  padding: 5px !important;}.p-sm {  padding: 10px !important;}.p-md {  padding: 15px !important;}.p-lg {  padding: 20px !important;}.p-xl {  padding: 25px !important;}复制代码

虽然在实际应用时,尺寸型写法并没有什么不妥,但很明显它的扩展性很差,而且不直观。作为例子,我只写了五个数值,但如果我们希望添加更多的 padding 值的话,尺寸型命名就乏力了。我认为,凡是可以量化的属性,比如 paddingmarginfont-sizeborder-width 等,应该直接用数值表示,而对于不可以量化的属性,比如 box-shadow,用尺寸型命名比较合适。

精简命名

大多数的 helpr 命名都是 CSS 属性的首字母缩写形式。比如 p 表示 paddingm 表示 marginf-s 表示 font-size 等。这符合我们期望的简洁直观的要求。但也不能唯缩写论,所有的命名都用缩写,因为有些属性的缩写会重复,而且有些缩写之后就不知道具体含义了。我们可以沿用之前的规则,可以量化的属性都用缩写,不可以量化的属性用简化的全称(比如 box-shadow 可以替换为 shadow)。

以 padding 循环为例:

@for $counter from 0 through 6 {    .p-#{ $counter * 5 } {        padding: ($counter * 5px) !important;    }    .p-t-#{ $counter * 5 } {        padding-top: ($counter * 5px) !important;    }    .p-r-#{ $counter * 5 } {        padding-right: ($counter * 5px) !important;    }    .p-b-#{ $counter * 5 } {        padding-bottom: ($counter * 5px) !important;    }    .p-l-#{ $counter * 5 } {        padding-left: ($counter * 5px) !important;    }}复制代码

对于其它几个 helper 与此类似,循环也很简单。

关于 Margin 负值

margin 的 helper 相比其它来说比较特殊,因为它有负值,所以我们必须考虑如何表示负值。有些框架用 n (negtive)表示负值。比如 m-{t,r,b,l}-n-* 的形式:

.m-t-n-5 {  margin-top: -5px !important;}.m-r-n-5 {  margin-right: -5px !important;}.m-b-n-5 {  margin-bottom: -5px !important;}.m-l-n-5 {  margin-left: -5px !important;}复制代码

我觉得完全可以简化一步,用 - 表示负值,简单易懂,如下:

.m-t--5 {  margin-top: -5px !important;}.m-r--5 {  margin-right: -5px !important;}.m-b--5 {  margin-bottom: -5px !important;}.m-l--5 {  margin-left: -5px !important;}复制代码

虽然这种命名方式很简洁,但看上去和其它 helper 不太统一。

关于圆角

圆角的 CSS 属性名为 border-radius,如果直接简写的话和 border-right 就重复了,参见其它框架的表示方法有 corner-roundedrounded 等。我们也可以简化一下,比如直接用 r 表示,既可以代表  rounded 也可以代表 radius,一举两得。这样的表示方法应该不会有歧义,毕竟在我们的脑海中,r 表示半径算是一个根深蒂固的概念。Sass 代码如下:

@for $counter from 0 through 10 {    .r-#{ $counter } {        border-radius: ($counter * 1px) !important;    }    .r-t-l-#{ $counter } {        border-top-left-radius: ($counter * 1px) !important;    }    .r-t-r-#{ $counter } {        border-top-right-radius: ($counter * 1px) !important;    }    .r-b-r-#{ $counter } {        border-bottom-right-radius: ($counter * 1px) !important;    }    .r-b-l-#{ $counter } {        border-bottom-left-radius: ($counter * 1px) !important;    }}复制代码

我们用 -full 表示 100%,其它框架也基本如此,稍后再谈论 r-100% 这种形式的可行性及问题所在。

.r-full {    border-radius: 100%}.r-t-l-full {    border-top-left-radius: 100%}.r-t-r-full {    border-top-right-radius: 100%}.r-b-r-full {    border-bottom-right-radius: 100%}.r-b-l-full {    border-bottom-left-radius: 100%}复制代码

同样的,高度和宽度的 100% 数值也用 -full 表示,循环方式类似。

关于阴影

我们在之前反复提到了阴影属于非量化的属性,所以只能使用尺寸型命名法,当然用数字也不是不可以,一会儿再详细说明。先看源代码:

.shadow-xs{    box-shadow:0 1px 5px 1px rgba(0,0,0,.15);}.shadow-sm{    box-shadow:0 2px 10px 2px rgba(0,0,0,.15);}.shadow-md{    box-shadow:0 3px 20px 3px rgba(0,0,0,.15);}.shadow-lg{    box-shadow:0 4px 30px 4px rgba(0,0,0,.15);}.shadow-xl{    box-shadow:0 5px 40px 5px rgba(0,0,0,.15);}复制代码

整体而言,比较简洁,不过阴影的数值我是粗略添加的,实际情况要做调整。说点题外话,我个人觉得对于非量化的属性本身而言,或许用处就不大,因为这些属性能够满足业务需求的可能微乎其微,但是它仍然是不可获取的一部分。所以说“通用的” helper 并不一定通用。

关于强度表示法

通过 font-weight 说一下关于强度的表示法,font-weight 的 CSS 属性本身就有两种表示法,一种是直接文字命名,比如 .f-s-thin , .f-s-normal, .f-s-bold 等,另一种是比较直接的 100 ~ 900 数值型表示法。以我个人观点,我更倾向于数值型表示法,简单直观,并没有歧义,也算是约定俗成的规定吧。font-weight 的循环比较简单,而且数值有限,我们可以直接写出从 100 ~ 900 的所有 helper。其它类似的 helper 也可以用 100 ~ 900 表示强度,比如颜色。

需要注意的是,编写 helper 时一定要对数值型、尺寸型、强度型命名做好归类与统一,切记毫无章法地胡乱使用。

类命名中的特殊字符

对于 r-100% 或者 w-100% 这样的写法是可以的,但是在定义 CSS 时要进行字符转义,比如

.r-100\% {    border-radius: 100%}复制代码

使用方式如下

复制代码

但是这种写法总给人怪怪的感觉,而且输入时要按 shift + %,不太方便,所以暂时只作为参考。 另外说明一点,我们可以通过特殊字符定义百分数,比如:

.w-50 {   width: 50px;}.w\:50 {   width: 50%}复制代码

通过约定的这种规则,我们就可以为 helper 添加栅格系统了。不过这只是暂时的想法,毕竟我们已经有一套轻量级 CSS 框架了。

序列数量

因为 helper 是循环生成的,所以循环的数量决定了 helper 的丰富度。那么循环的数量多少合适呢?这是所有 helper 最难统一的地方。不可否认,helper 的数量越多,通用性越强,也就越灵活。任何事物都有两面性,虽然 helper 越多越好,但是数量太多会造成文件臃肿。目前我写的 helper 的文件体积几乎和之前的轻量级框架差不多,某种程度上来说确实在向“零件化”的框架发展。另一方面,其实 helper 并没有必要写的太全面,很多数值会造成冗余。

简单来说,对于有限值的 helper 就可以全部写出,比如对其方式、font-weight 等。而对于任意数值的 helper 来说,我们需要选择常用的一些数值,比如 paddingmargin 等属性,基本 1~50 px 之间就可以了,而圆角 1~20 px 足矣。不能量化的属性比如阴影就完全看个人喜好了,我觉得五个尺寸就差不多。对于实在特殊的需求也只能特殊对待了。

演示

现在我们测试一下我们所写的 helper 是不是能够满足一般需求,比如一个带有圆角阴影的用户卡片,如下:

See the Pen

这个实例全部是用 helper 完成的,可惜这套 helper 没有栅格系统,所以布局并不灵活,但是结合之前的轻量级框架,会显示出它强大的功能。

总结

编写 helper 比编写框架要容易的多,但简单易用、通俗易懂的 helper 还需要严谨的思考,详细的 helper 可以参见 源码。虽然我一直声称没有打算把 helper 写成一个框架,但随着细节的追加与调整,比如添加栅格系统,这个通用的 helper 已经趋向于一个“零件化”的框架了。至于组件式框架和零件式框架哪个更好,这是一个很难选择的问题。但是我更倾向于组件与零件的结合,因为我不希望整个 HTML 文件被冗长的 CSS 类装饰的支离破碎。

转载地址:http://lndxl.baihongyu.com/

你可能感兴趣的文章
专线与***冗余方案
查看>>
Go语言中的方法(Method Sets)
查看>>
嵌入式系统构件学习推荐的书 ucos的作者所著
查看>>
Android中内容提供者ContentProvider的理解与基本使用
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
使用yaml语言来写配置文件
查看>>
go 入门学习笔记之 变量/常量/基本类型 (五)
查看>>
Android ActionBar居中显示标题
查看>>
硬盘的存储原理和内部架构
查看>>
爆笑配音神作来袭,新白娘子传奇相亲记
查看>>
android线程使用注意问题?【安卓进化二】
查看>>
常用JS方法
查看>>
hive优化--增加减少map数
查看>>
php-fpm配置
查看>>
【 D3.js 选择集与数据详解 — 2 】 使用data()绑定数据
查看>>
SomethingOn生产力提升工具使用
查看>>
beyond programming
查看>>
【转】NET-SNMP安装过程
查看>>
2012-06-18 16:20 ECSHOP用URL重写进行SEO优化
查看>>