开头
从18年8月开始,我开始了我的野生前端职业生涯。不管是自学期间还是工作之后,网上的文章对我的学习帮助良多。所以我想开始分享一些我没在网上看到过的知识。
图片载体
通常我们展示图片是用html的标签或者css的
background-image
属性。
由于安卓手机会对点击的进行放大显示,所以本人喜欢用
background-image
多一点。
安卓点击默认放大的解决方法:css可以用
pointer-events:none
;js可用e.preventDefault()
当然这两种载体还有其他区别,可以自行去搜索,下面就只用background-image
来作为图片的载体。
自动获取图片宽高
不知道有没有人和我一样,工作中写的页面大多数是通过图片堆砌起来的,不论是通过一些开发辅助工具(pxcook等),都要查看每张图片的宽高,所以自从我看到了Less中有获取图片宽高的函数后,我就和Less擦出了火花。
.logo {
width: image-width("logo.png");
height: image-height("logo.png");
}
编译成
.logo {
width: 10px;
height: 20px;
}
复制代码
先说下这个函数的缺点,用多了之后会使项目的编译速度变慢(包括热更新),如果你的电脑本身就慢的话不推荐用。
1、首先要配置rem和把函数封装成mixin
移动端中的适配直接使用px单位是不行的,所以我们要进一步的改写
@designWidth: 750;
html {
//因为移动端已经兼容了vw和calc,所以不再需要用js来配置rem
font-size: calc(10000vw / @designWidth)
}
.image-size(@url) {
width: unit(image-width(@url) / 100, rem);
height: unit(image-height(@url) / 100, rem);
}
复制代码
2、配置background-image的mixin
首先我们的图片都要放在路径是src/assets/img/
的文件下,而不是和组件放在一起
.contain {
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.image-size(@url) {
width: unit(image-width(@url) / 100, rem);
height: unit(image-height(@url)/ 100, rem);
}
.bg-contain (@url) {
// 路径是从项目的根目录开始的
.image-size('./src/assets/img/@{url}');
// 这里使用webpack来解析图片模块
background-image: url('~@/assets/img/@{url}');
// 使用继承减少生成的css代码量
&:extend(.contain);
}
使用如下
.logo {
.bg-contain('logo.png');
}
.homeLogo {
.bg-contain('home/logo.png');
}
复制代码
3、进一步减少bg-contain()的代码量
在进一步改写之前我们先来了解下Less的List Functions。
@paths: 'home', 'index';
value: extract(@paths, 1);
编译成
value: 'home';
复制代码
很明显这就是以1为开始下标的数组,并且可以通过extract()
函数取值。
有三处可以减少我们的代码量
- 图片处于的文件夹目录
- 图片的格式
- 参数差异化兼容
@paths: '/img';
.bg-contain (@name, @arg1: 'png', @arg2: 1) {
// 暂时没想到更漂亮的方法来兼容参数的差异化
// 有想到的话请务必告诉我
@suffix1: if(isstring(@arg1), @arg1, '');
@suffix2: if(isstring(@arg2), @arg2, '');
@pathIndex1: if(isnumber(@arg1), @arg1, 0);
@pathIndex2: if(isnumber(@arg2), @arg2, 0);
@suffix: @suffix1 + @suffix2;
@pathIndex: @pathIndex1 + @pathInde2;
@path: extract(@paths, @pathIndex);
.image-size('./src/assets/@{path}/@{name}.@{suffix}');
background-image: url('~@/assets/@{path}/@{name}.@{suffix}');
&:extend(.contain);
}
使用如下
// home.vue
@paths: '/img/home';
.logo {
.bg-contain('logo');
}
.gif {
.bg-contain('logo', 'gif');
}
.test {
.bg-contain('logo', 'gif', 1);
}
// index.vue
@paths: '/img/index', '/img/common';
.logo {
.bg-contain('logo');
}
.commonLogo {
.bg-contain('logo', 2);
}
复制代码
4、用遍历来减少代码量
我用的循环可不是loop when这种那么恶心的东西,而是用Less v3.7.0 版本的新特性each()来进行遍历。
首先让我们来看一下怎么用each()来减少代码量
@imgs: logo, avatar;
each(@imgs, {
.bg-@{value} {
.bg-contain(@value);
}
)
复制代码
不知道你们有没有和我一样看到这段后感觉很爽,不过这里要注意一下。
当我们要用遍历出来的@value
来作为选择器时,我们的数组里放的元素是不能带引号的,不过我们可以通用Less的e()
函数来去引号。
因为在Less中带引号的是Value
类型,而不带引号的是Node
类型,只有Node
类型可以用来作为选择器使用。感兴趣的话可以看下Less的源码。
自动引入图片
上面的代码还是要在css里写图片名字然后在html里写上相应的class,感觉写的有点不舒服。不知道你们有没有想到怎么连css都不写就能用图片呢。
我先说下我的思路:
- 获取图片路径和规范化图片的class命名。
- 把图片路径和类名分别定义成全局变量引入。
- 在less中遍历数组,配置类名和引入图片资源。
是不是很简单?
当然这种方式是有缺点的,就是不能动态地更新自动引入的图片,所以如果用这种方法来自动引入图片的话,你需要在yarn serve
前就把要用到的图片给放在图片目录下。
下面我就用 Vue + Node + Less 来做自动引入图片。
这里我用 vue-cli 3.0 来生成项目,然后在项目根目录下配置 vue.config.js 文件。
1、定义遍历函数
2、生成Less的全局变量对象
3、输出配置
4、遍历全局数组生成类
5、关于class的作用域限制
你当然可以使用上面的前置字符串来限制class的作用域,使用如下:
<div class="bg-logo"/>
复制代码
我这里还有一种我喜欢的方式来限制class的作用域,不过肯定不是人人都喜欢的方式,首先看看怎么使用:
// html版
<bg logo/>
// pug版
bg(logo)
复制代码
极简主义,有没有!!!
首先我们知道
这个标签是不存在的,对于这种标签浏览器是会把它看成inline-block
,所以我们要把
的 display
属性定义为block
。(这里我没有看HTML的规范,所以如果说的不准确的话请大家指出)。
bg {
display: block;
}
复制代码
然后如果直接在 vue 里的中使用这种不存在的HTML标签的话,vue 会从当前组件配置的components属性中找有没有这个组件,没有的话会报错,虽然报错不会影响输出结果,但是看着报错心里就不舒服了,所以我们可以改一下vue源码的
isHTMLTag
变量,在makeMap
中加一个bg
字符串。
结尾
第一次写这种分享文章,可能有的地方写的不好,请多多包涵。
其实Less还有很多很棒的特性,比如 @plugin
Maps
range()
等。
最后,知道我为什么后半段都用图片吗?就是想你们参观一下我的 ✨0 star✨github。