【记一忘三二】Less如何使用函数、混入、插件适配移动端

516 阅读2分钟

起因

最近在做移动端官网开发,决定采用vw做响应式,但设计图是375px宽度,所以需要每块元素的px单位转为vw单位*

JS还好说,通过函数很容易就封装了

function px2vw(value) {
    return (value / 375) * 100 + "vw";
}

但是在Less的语法呀,又该如何去封装喃?

解决方案

以设计稿375px*667px为例,兼容处理尺寸为宽度50px*50px的div元素

变量

@designWidth: 375;


div {
  width: unit((50/ 375 * 100), vw);     // 13.33333333vw
  height: unit((50 / 375 * 100), vw);	// 13.33333333vw;
}

这样使用虽然能够达到所需的效果,但是并不符合复用的原则

混入

// unit.scss
@designWidth: 375;

.px2vw(@name, @px) {
  @{name}: unit((@px / @designWidth * 100), vw);
}

// test.less
@import "unit.less";

div {
  .px2vw(width, 50);		// 13.33333333vw
  .px2vw(height, 50);		// 13.33333333vw
}

混入解决了复用的问题,但又引入一个新问题,transform: translateX(50px);margin: 50px 30px;此类语法并不能解决

当然创建这些属性的专属混入就可以了

.transformTranslateX(@px) {
  transform: translateX(unit((@px / @designWidth * 100), vw));
}

但这并不符合偷懒原则

混入+返回值

less文档中有详细的语法介绍,这里就不班门弄虎了

// unit.scss
@designWidth: 375;

.px2vw(@px) {
  @result: unit((@px / @designWidth) * 100, vw);
}

// test.less
@import "unit.less";

div {
  width: .px2vw(50) [];			// 13.33333333vw
  height: .px2vw(50) [];		// 13.33333333vw
}

这样偷懒原则也符合了,但但但是,末尾要加[]很丑陋,不符合审美原则!!!

@functions

使用这种方式首先需要修改lessjavascriptEnabled配置,开启less文件内联 JavaScript

vue-cli5为例,修改vue.config.js配置文件

module.exports = {
  css: {
    loaderOptions: {
      less: {
        lessOptions: {
          javascriptEnabled: true,
        },
      },
    },
  },
};

下面才能开始使用

(function () {
  let designWidth = 375;
  this.px2vw = function (px) {
    return (px / designWidth) * 100 + "vw";
  };
})();
// unit.scss
.initFun(){
  @functions: ~`(function () {
    let designWidth = 375;
    this.px2vw = function (px) {
      return (px / designWidth) * 100 + "vw";
    };
  })();`;
}
.initFun();

// test.less
@import "unit.less";

div {
  width:  ~`px2vw(50)`;			// 13.33333333vw
  height:  ~`px2vw(50)`;		// 13.33333333vw
}

感觉更丑陋了,有木有!!!

刚好less也弃用了该语法,经测试在"less": "^4.1.3"中还是能使用

image-20240620005015376

注意看图中替换方案,因为这将是本文的主角

@plugin(推荐)

老规矩,想了解更多语法,请看less文档

首先定义unit-plugin.js

// unit-plugin.js

module.exports = {
  install: function (less, pluginManager, functions) {
    functions.add("px2vw", function (param) {
      return (param.value / 375) * 100 + "vw";
    });
  },
};

// test.less
@plugin "./unit-plugin.js";

div {
  width: px2vw(50);			// 13.33333333vw
  height: px2vw(50);		// 13.33333333vw
}

完美解决问题了!!!

下面不属于本文的主要内容,可以略过。。。

项目中

@plugin使用方案有两种,还是以vue-cli5为例

全局less文件(推荐)

定义全局less文件

// global.less

@plugin "~@/assets/css/less-plugin.js";
// vue.config.js

module.exports = {
    // 设置全局less文件
  pluginOptions: {
    "style-resources-loader": {
      preProcessor: "less",
      patterns: [path.resolve(__dirname, "src/assets/css/global.less")],
    },
  },
}

具体如何全局引入less文件根据当前环境有不同的解决方案

定义插件

// vue.config.js

module.exports = {
  css: {
    loaderOptions: {
      less: {
        lessOptions: {
          plugins: [
            new (class {
              constructor() {}
              install(less, parser, functions) {
                functions.add("px2vw", function (param) {
                  return (param.value / 375) * 100 + "vw";
                });
              }
            })(),
          ],
        },
      },
    },
  },
};