更新的答案:
正如下面评论中seven-phases-max所提到的,他创建了一个非常棒的自定义Less插件,允许我们在Less中编写函数(是的,带有返回值),并在规则内使用它们。
为了使用这个插件,我们必须先通过执行以下命令来安装插件:
npm install -g less-plugin-functions
下一步是编写自定义函数。操作语法是首先将函数包装在名为
.function {}
的 mixin/selector 块中,然后只需复制粘贴我在原始答案中提供的 mixin 代码(见下文)。唯一的更改是必须用
return
替换
@output
变量,因为该函数返回分配给此属性的值。因此,代码如下所示:
.function{
.get-vw(@target) {
@vw-context: (1440 * 0.01) * 1px;
return: (@target / @vw-context) * 1vw;
}
}
一旦函数被创建,使用起来非常简单明了,就像我们在 Sass 中所做的一样:
.selector {
font-size: get-vw(20px);
margin-top: get-vw(16px);
}
现在,下一步是编译Less文件以生成输出的CSS。使用命令行编译需要使用相同的lessc
命令,但我们必须在执行时包含/调用自定义插件。因此,编译语句应如下所示:
lessc --functions test.less test.css
所有这些信息都已经在
GitHub页面中提供,但为了完整性和安全起见,我已经在回答中再次记录了它们。
注意:如果自定义函数中没有指定
return
属性,则在编译过程中将抛出以下错误:
RuntimeError: error evaluating function
get-vw
:
[plugin-functions] can't deduce return value, either no mixin matches or return statement is missing in [file name]
首先要明确的是,在Less中无法编写真正的函数,因为不可能使用
return语句。
我们可以做的一件事是编写一个mixin并绕开障碍,使其行为更接近于函数。下面是一个示例:
.get-vw(@target) {
@vw-context: (1440 * 0.01) * 1px;
@output: (@target / @vw-context) * 1vw;
}
.parent {
.get-vw(20px);
font-size: @output;
.child {
.get-vw(16px);
padding: @output;
}
}
但是上面代码片段的问题在于,如果两个属性需要使用此函数的输出,并且它们各自具有不同的输入值,则由于Less中变量的惰性加载,将会出现问题。例如,请考虑下面的代码片段(
.get-vw
mixin与先前的代码相同)。
.parent {
.get-vw(20px);
font-size: @output;
.get-vw(16px);
margin-top: @output;
}
您可能期望的输出如下所示:
.parent {
font-size: 1.38888889vw;
margin-top: 1.11111111vw;
}
但实际输出将是这样的:(
您可以看到,相同的值应用于两个位置)
.parent {
font-size: 1.38888889vw;
margin-top: 1.38888889vw;
}
解决方案是变得更加具有hacky性质,将每个这样的属性放置在一个未命名的命名空间(
&
)中,并因此为每个属性提供自己的作用域:
.parent {
& {
.get-vw(20px);
font-size: @output;
}
& {
.get-vw(16px);
margin-top: @output;
}
}
如您所见,这一切都变得非常混乱。在Less中编写真正的函数的唯一方法是编写自定义插件,就像Bass Jobsen在这里描述的那样。这是复杂的,但这是唯一的真正方法。
.get-vw(1);
然后将返回值乘以所需大小:font-size: @output * 20;
或margin-top: @output * 16;
这简单地避免了多次调用mixin和创建单独的作用域。但这仍不完美。我会尝试使用插件! - Ryan