使用LESS mixin多次设置变量,但得到错误的结果 [英] Using LESS mixin to set variable multiple times but getting wrong results

查看:188
本文介绍了使用LESS mixin多次设置变量,但得到错误的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在前面,我今天开始少了...

At the front, I started with less today...

因此,欢迎提出任何建议以更好地做到这一点!

So any advice how to do that better is welcome!

我有以下.less文件:

I have following .less file:

.test(@target;@context) {
  @em: (@target / @context) * 1em;
}

.custom-field {
  position: relative;
  .test(30;16);
  padding-bottom: @em;
  .test(30;16);
  margin-bottom: @em;
  .test(320;16);
  max-width: @em;
}

我希望padding-bottom和margin-bottom的值分别为1.875和max-width:20.

I expect that padding-bottom and margin-bottom getting the value 1.875 and max-width: 20.

但是多数民众赞成在输出:

But thats the output:

.custom-field {
  position: relative;
  padding-bottom: 1.875em;
  margin-bottom: 1.875em;
  max-width: 1.875em;
}

一开始我将第二个参数作为可选参数.但是为了进行测试,我使它变得尽可能简单.

I had the second parameter as an optional parameter at the start. But for testing I made it as simple as possible.

如果我更频繁地使用mixin,我会得到更多奇怪的结果.至少对我来说,他们很奇怪:)

If I use the mixin even more often, I get a lot more weird results. At least for me they are weird :)

有人对我有建议吗?

推荐答案

LESS变量延迟加载" ,这意味着它们在代码中出现的顺序无关紧要,通常是最后一次"调用获胜.在您的情况下,我发现奇怪的是,我希望它们全部为20em,因为那是该值的最后"设置.但是,我从发布此问题"中了解到,这是因为由mixin调用,它是仅设置的第一个值.由于延迟加载,可能会影响调用该变量的整个作用域,而且由于mixin只会设置一次该值,无论调用多少次,您最终都会看到奇怪"的行为.

LESS variables "lazy load", which means the order they appear in the code does not matter, it is generally the "last" call that wins. What what I found odd in your case is that I would have expected them all to be 20em since that is the "last" setting of the value. However, I learned from posting this "issue" that it is specifically because it is being called by a mixin that it is the first value only that is set. Because of the lazy loading, it can affect the whole scope the variable is called with, and because a mixin will only set the value once no matter how many times called, you end up with what can seem like "odd" behavior.

您至少有四种方法可以处理您的情况,这些方法将输出您想要的内容.

You have at least four ways that may handle your situation, which will output what you desire.

.test(@target;@context;@prop) {
  @{prop}: (@target / @context) * 1em;
}

.custom-field {
  position: relative;
  .test(30;16;padding-bottom);
  .test(30;16;margin-bottom);
  .test(320;16;max-width);
}

(2)设置全局Javascript函数

请仔细注意它的构造/使用方式.我从此主题.可以通过这种方式设置各种功能.

(2) Set a Global Javascript Function

Notice carefully how this is constructed/used. I got the idea from this thread after your comment about SASS. Various functions could be set up this way.

@setEm: `setEm = function(target,context) { return ((target/context)+'em'); }`;

.custom-field {
  position: relative;
  padding-bottom: ~`setEm(30,16)`;
  margin-bottom: ~`setEm(30,16)`;
  max-width: ~`setEm(320,16)`;
}

(3)具有模式匹配的非JavaScript解决方案

请仔细注意其构造/使用方式.这比较冗长",但确实避免了对javascript环境的调用(如果需要的话,或者如果它们有时删除了内联javascript功能 [已在网站上的各种问题中进行了讨论] ),并提供了很好的灵活性.也可以使用它来设置各种功能(如图所示).

(3) Non-Javascript Solution with Pattern Matching

Notice carefully how this is constructed/used. This is more "verbose", but does avoid a call to the javascript environment (if such is desired, or if they at sometime remove inline javascript functionality [which has been discussed during various issues on the site]) and gives some good flexibility. Various functions can be set up with this as well (as illustrated).

/*make a global setter for local variable getter (this will get up to six  
/*values from the same caller function to avoid variable overlap; should you 
/*need more within a single scope block, just expand this).
*/

.setGetInstance(@num) {
  .-(@num);
  .-(1) { @getVar1: @setVar;}
  .-(2) { @getVar2: @setVar;}
  .-(3) { @getVar3: @setVar;}
  .-(4) { @getVar4: @setVar;}
  .-(5) { @getVar5: @setVar;}
  .-(6) { @getVar6: @setVar;}
}

/*Create various "function" mixins that use the global setter */

.setEm(@target;@context;@num) {
  @setVar: ((@target / @context) * 1em);
  .setGetInstance(@num);
}
.-100(@target;@num) {
  @setVar: (@target - 100px);
  .setGetInstance(@num);
} 

/*Use the function mixins (up to six per block in this example) */

.custom-field1 {
  position: relative;
  .setEm(30;16;1;);
  padding-bottom: @getVar1;
  .setEm(30;16;2);
  margin-bottom: @getVar2;
  .setEm(320;16;3);
  max-width: @getVar3;
}
.custom-field2 {
  .setEm(20;10;1;);
  padding-bottom: @getVar1;
  .setEm(10;10;2);
  margin-bottom: @getVar2;
  .minus100(1000;3);
  max-width: @getVar3;
}

CSS输出

.custom-field1 {
  position: relative;
  padding-bottom: 1.875em;
  margin-bottom: 1.875em;
  max-width: 20em;
}
.custom-field2 {
  padding-bottom: 2em;
  margin-bottom: 1em;
  max-width: 900px;
}

(4)使用嵌套块或Mixins

我从此评论了解了另一种方法,该方法也解决了该问题以另一种方式.

(4) Using Nested Blocks or Mixins

I learned another method from this comment which also resolves the issue in a different way.

.setEm(@target;@context) {
  @em: ((@target / @context) * 1em);
}

.custom-field {
  position: relative;
  & {padding-bottom: @em; .setEm(30;16);}
  & {margin-bottom: @em; .setEm(30;16);}
  & {max-width: @em; .setEm(320;16);}
}

但是,这将在1.6.2之前的任何LESS版本中产生多个选择器块,就像这样(1.6.2+将其全部合并,请参见7-phases-max的注释):

However, this will produce multiple selector blocks in any version of LESS prior to 1.6.2, like so (1.6.2+ merges it all, see seven-phases-max's comment):

.custom-field {
  position: relative;
}
.custom-field {
  padding-bottom: 1.875em;
}
.custom-field {
  margin-bottom: 1.875em;
}
.custom-field {
  max-width: 20em;
}

因此,如果使用早期版本,最好将其保留为本地mixin:

So it is better to keep it as a local mixin if using an earlier version:

.custom-field {
  position: relative;
  .-() {padding-bottom: @em; .setEm(30;16);}
  .-() {margin-bottom: @em; .setEm(30;16);}
  .-() {max-width: @em; .setEm(320;16);}
  .-() 
}

将全部分组:

.custom-field {
  position: relative;
  padding-bottom: 1.875em;
  margin-bottom: 1.875em;
  max-width: 20em;
}

这篇关于使用LESS mixin多次设置变量,但得到错误的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆