Less的圖片管理

開頭

從18年8月開始,我開始了個人野生前端職業生涯。不論是自學期間仍是工做以後,網上的文章對個人學習幫助良多。因此我想開始分享一些我沒在網上看到過的知識。css

圖片載體

一般咱們展現圖片是用html的<img>標籤或者css的background-image屬性。html

因爲安卓手機會對點擊的<img>進行放大顯示,因此本人喜歡用background-image多一點。前端

安卓<img>點擊默認放大的解決方法:css能夠用pointer-events:none;js可用e.preventDefault()vue

固然這兩種載體還有其餘區別,能夠自行去搜索,下面就只用background-image來做爲圖片的載體。webpack

自動獲取圖片寬高

不知道有沒有人和我同樣,工做中寫的頁面大多數是經過圖片堆砌起來的,不管是經過一些開發輔助工具(pxcook等),都要查看每張圖片的寬高,因此自從我看到了Less中有獲取圖片寬高的函數後,我就和Less擦出了火花。git

.logo {
        width: image-width("logo.png");
        height: image-height("logo.png");
    }
    
    編譯成
    
    .logo {
        width: 10px;
        height: 20px;
    }
複製代碼

先說下這個函數的缺點,用多了以後會使項目的編譯速度變慢(包括熱更新),若是你的電腦自己就慢的話不推薦用。github

一、首先要配置rem和把函數封裝成mixin

移動端中的適配直接使用px單位是不行的,因此咱們要進一步的改寫web

@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);
    }
複製代碼

二、配置background-image的mixin

首先咱們的圖片都要放在路徑是src/assets/img/的文件下,而不是和組件放在一塊兒vue-cli

.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');
    }
    
複製代碼

三、進一步減小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);
    }
複製代碼

四、用遍從來減小代碼量

我用的循環可不是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 文件。

一、定義遍歷函數

二、生成Less的全局變量對象

三、輸出配置

四、遍歷全局數組生成類

五、關於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

相關文章
相關標籤/搜索