LESS: How can I pass a mixin as an argument to another mixin?

匿名 (未验证) 提交于 2019-12-03 02:16:02

问题:

I have some basic mixins that apply some rules using media queries

.on-small(@rules) {   @media (@minWidthSmall) { @rules(); } }  .on-medium(@rules) {   @media (@minWidthMedium) { @rules(); } }  // and .on-large, .on-x-large and so on 

And I'm trying to build a very simple flex-based grid system, I'm trying to pass the mentioned mixins as parameters so I can have a generic .make-column mixin. as follows:

.make-col(@break-point-mixin, @span, @size) {   flex: 1;   box-sizing: border-box;     /***********************************************************   Is the following line possible in LESS somehow?   ***********************************************************/   @break-point-mixin({     width: percentage(@span/@size);     min-width: percentage(@span/@size);   }); }  .grid-col-on-small(@span: 1, @size: 1) {   .make-col(@break-point-mixin: .on-small, @span, @size); }  .grid-col-on-medium(@span: 1, @size: 1) {   .make-col(@break-point-mixin: .on-medium, @span, @size); } 

But unfortunately passing @break-point-mixin as a parameter and calling it from inside .make-col crashes with:

Unrecognised input. Possibly missing opening '('

回答1:

In this particular case (unlike a general case with an arbitrary mixin name) I'd say you're missing the fact that in .on-small/.on-medium these small and medium things are also nothing but parameters and thus should not be a part of the mixin names. With this in mind your example becomes:

.on(small, @rules) {   @media (@minWidthSmall) {@rules();} }  .on(medium, @rules) {   @media (@minWidthMedium) {@rules();} }  .make-col(@device, @span, @size) {   flex: 1;   box-sizing: border-box;   .on(@device, {     width: percentage(@span/@size);     min-width: percentage(@span/@size);   }); }  // usage:  .make-col(small, @span, @size); 

Same for your .grid-col-on-* mixins, they are just a single:

.grid-col-on(@device, @span: 1, @size: 1) {   .make-col(@device, @span, @size); } 

and so on.

If you really want a flexible/generic grid - never hardcode device/breakpoint names into mixin or variable names (for more rationale and examples see https://github.com/less/less.js/issues/2702).



回答2:

No, you can't send a mixin name as a parameter and use it in that way.

Instead you can do something like the below where the media query mixin is called directly from within the wrapper mixin instead of the .make-col mixin. As the wrapper mixin is aware of the variables that the media query mixin needs this wouldn't result in any problems.

.grid-col-on-small(@span: 1, @size: 1) {   .make-col(@span, @size);   .on-small({     width: percentage(@span / @size);     min-width: percentage(@span / @size);   }); }  .grid-col-on-medium(@span: 1, @size: 1) {   .make-col(@span, @size);   .on-medium({     width: percentage(@span / @size);     min-width: percentage(@span / @size);   });   } 

If you are concerned about rewriting the rules in the above mixins then you can set them to a ruleset like below and use it.

@colRules: {              width: percentage(@span / @size);              min-width: percentage(@span / @size);            };  .grid-col-on-small(@span: 1, @size: 1) {   .make-col(@span, @size);   .on-small(@colRules); }  .grid-col-on-medium(@span: 1, @size: 1) {   .make-col(@span, @size);   .on-medium(@colRules);   } 

Or, you can send the mixin name as a parameter and use guards like below. As we are dealing with break-points here and there shouldn't be lots of them, this approach should help and would probably get my vote.

@colRules: {              width: percentage(@span / @size);              min-width: percentage(@span / @size);            };  .make-col(@breakpoint, @span, @size) {   flex: 1;   box-sizing: border-box;   & when (@breakpoint = s) {     .on-small(@colRules); /* or you could replace this with that mixin's content also */   }   & when (@breakpoint = m) {     .on-medium(@colRules);   }   /* and so on for the rest */ }  .grid-col-on-small(@span: 1, @size: 1) {   .make-col(s, @span, @size); }  .grid-col-on-medium(@span: 1, @size: 1) {   .make-col(m, @span, @size); } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!