Less的图片管理

开头

从18年8月开始,我开始了我的野生前端职业生涯。不管是自学期间还是工作之后,网上的文章对我的学习帮助良多。所以我想开始分享一些我没在网上看到过的知识。

图片载体

通常我们展示图片是用html的<img>标签或者css的background-image属性。

由于安卓手机会对点击的<img>进行放大显示,所以本人喜欢用background-image多一点。

安卓<img>点击默认放大的解决方法: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)
复制代码

极简主义,有没有!!!


首先我们知道<bg />这个标签是不存在的,对于这种标签浏览器是会把它看成inline-block,所以我们要把<bg />display属性定义为block。(这里我没有看HTML的规范,所以如果说的不准确的话请大家指出)。

    bg {
        display: block;
    }
复制代码

然后如果直接在 vue 里的<template>中使用这种不存在的HTML标签的话,vue 会从当前组件配置的components属性中找有没有这个组件,没有的话会报错,虽然报错不会影响输出结果,但是看着报错心里就不舒服了,所以我们可以改一下vue源码的 isHTMLTag 变量,在makeMap中加一个bg字符串。

然后再改一下Less的遍历函数

好了,我已经想不到更简洁的方式引入图片了 over~

结尾

第一次写这种分享文章,可能有的地方写的不好,请多多包涵。

其实Less还有很多很棒的特性,比如 @plugin Maps range() 等。

最后,知道我为什么后半段都用图片吗?就是想你们参观一下我的 ✨0 stargithub

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值