跳到主要内容

@plugin At-Rules

发布 v2.5.0

导入 JavaScript 插件以添加 Less.js 函数和特性

编写你的第一个插件

使用 @plugin 规则与使用 .less 文件的 @import 类似。

@plugin "my-plugin"; // 如果没有扩展名,自动添加 .js

由于 Less 插件在 Less 范围内进行评估,因此插件定义可以非常简单。

registerPlugin({
install: function (less, pluginManager, functions) {
functions.add("pi", function () {
return Math.PI;
});
},
});

或者你可以使用 module.exports(在浏览器和 Node.js 中都可以使用)。

module.exports = {
install: function (less, pluginManager, functions) {
functions.add("pi", function () {
return Math.PI;
});
},
};

请注意,其它 Node.js CommonJS 约定(如 require())在浏览器中不可用。编写跨平台插件时请记住这一点。

插件可以做什么?很多,但让我们从基础知识开始。我们首先关注你可能放在 install 函数中的内容。假设你写了这个:

// my-plugin.js
install: function(less, pluginManager, functions) {
functions.add('pi', function() {
return Math.PI;
});
}
// etc

恭喜!你已经编写了一个 Less 插件!

如果你在样式表中使用它:

@plugin "my-plugin";
.show-me-pi {
value: pi();
}

你会得到:

.show-me-pi {
value: 3.141592653589793;
}

但是,如果你想将其乘以其它值或执行其它 Less 操作,则需要返回一个正确的 Less 节点。否则,你样式表中的输出是纯文本(这可能对你的目的来说是可以的)。

也就是说,这更正确:

functions.add("pi", function () {
return new tree.Dimension(Math.PI);
});

注意:维度是带有或不带单位的数字,例如 "10px",它将是 less.Dimension(10, "px")

现在你可以在操作中使用你的函数。

@plugin "my-plugin";
.show-me-pi {
value: pi() * 2;
}

你可能已经注意到,插件文件有可用的全局变量,即函数注册表(functions 对象)和 less 对象。这些是为了方便而存在的。

插件作用域

@plugin 规则添加的函数遵循 Less 作用域规则。这对于希望添加功能的 Less 库作者非常有用。

介绍命名冲突。

例如,假设你有两个来自两个第三方库的插件,它们都有一个名为“foo”的函数。

// lib1.js
// ...
functions.add("foo", function () {
return "foo";
});
// ...

// lib2.js
// ...
functions.add("foo", function () {
return "bar";
});
// ...

没问题!你可以选择哪个库的函数创建哪个输出。

.el-1 {
@plugin "lib1";
value: foo();
}
.el-2 {
@plugin "lib2";
value: foo();
}

这将产生:

.el-1 {
value: foo;
}
.el-2 {
value: bar;
}

对于共享其插件的插件作者,这意味着你还可以通过将其放置在特定范围内来有效地创建私有函数。例如,这将导致错误:

.el {
@plugin "lib1";
}
@value: foo();

从 Less 3.0 开始,函数可以返回任何类型的节点,并且可以在任何级别调用。

这意味着,在 2.x 中,这将引发错误,因为函数必须是属性或变量分配值的一部分:

.block {
color: blue;
my-function-rules();
}

在 3.x 中,情况不再如此,函数可以返回 At-Rules、Rulesets、任何其它 Less 节点、字符串和数字(后两者转换为匿名节点)。

空函数

有时你可能想调用一个函数,但你不想输出任何内容(例如存储以供以后使用的值)。在这种情况下,你只需要从函数返回false

var collection = [];

functions.add("store", function (val) {
collection.push(val); // imma store this for later
return false;
});
@plugin "collections";
@var: 32;
store(@var);

稍后,你可以执行以下操作:

functions.add("retrieve", function (val) {
return new tree.Value(collection);
});
.get-my-values {
@plugin "collections";
values: retrieve();
}

Less.js 插件对象

Less.js 插件应导出一个具有以下一个或多个属性的对象。

{
/* 在第一次导入插件时立即调用,仅一次。 */
install: function(less, pluginManager, functions) { },

/* 为每个@plugin实例调用。 */
use: function(context) { },

/* 在评估规则时为每个@plugin实例调用。
* 它只是在评估生命周期的后期 */
eval: function(context) { },

/* 将任意字符串传递给你的插件
* 例如 @plugin (args) "file";
这个字符串不会被解析,
因此它可以包含(几乎)任何内容*/
setOptions: function(argumentString) { },

/*设置最小的 Less 兼容性字符串
*你也可以使用一个数组,如[3,0]\*/
minVersion: ['3.0'],

/*仅用于 lessc,以解释
*终端中的选项\*/
printUsage: function() { },

}

PluginManager 实例用于install()函数,提供了添加访问者、文件管理器和后处理器的方法。

以下是一些示例存储库,展示了不同的插件类型。

预加载的插件

虽然@plugin调用在大多数情况下都很好用,但有时你可能想在解析开始之前加载插件。

请参见:“使用 Less.js”部分中的预加载插件以了解如何执行此操作。