Less.js: Selektor in einer Variablen speichern

Erstellt am 20. Apr. 2017  ·  50Kommentare  ·  Quelle: less/less.js

Wir haben diese Lösung:

// LESS
.selector {
    <strong i="6">@r</strong>: ~'.selector';

    &--mode {
        @{r}__block {
            prop: value;
         }
    }
}

// CSS
.selector--mode .selector__block {
  prop: value;
}

Ich schlage vor, eine Funktion hinzuzufügen: Schreiben Sie <strong i="9">@r</strong>: &; anstelle von <strong i="11">@r</strong>: ~".selector"; , um den aktuellen Selektor zu erhalten und in einer beliebigen Variablen zu speichern.

Beispiele:

// LESS
.selector {
  <strong i="15">@r</strong>: &; // .selector
}

.selector {
  &__inner {
    <strong i="16">@r</strong>: &; // .selector__inner
  }
}

.selector {
  &--modification &__inner {
    <strong i="17">@r</strong>: &; // .selector--modification .selector__inner
  }
}
feature request medium priority needs decision research needed

Alle 50 Kommentare

Seltsamerweise war ich mir absolut sicher, dass eine solche Anfrage bereits existiert. Offenbar ist es das nicht.
(Obwohl die Idee offensichtlich schon in vielen Tickets auftauchte: #1174, https://github.com/less/less.js/issues/1075#issuecomment-16891103 etc.)
Also lass es sein, denke ich.


Übrigens, nur für alle Fälle (und um einige Anwendungsfälle zu sammeln, um an mögliche Impl.-/Syntaxkonflikte zu denken):
Wie werden Sie es verwenden? Ich vermute, dass es in vielen Fällen aufgrund der faulen Bewertung nicht so funktioniert, wie Sie es erwarten. Z.B:

a {
    <strong i="11">@r</strong>: &;
    b {
        something: @r;
    }
}

wird darin enden, dass:

a b {
    something: a b; // not a!
}

Weil der @r wirklich innerhalb von a b ausgewertet wird (dh dort, wo er verwendet wird - nicht an dem Punkt, an dem Sie ihn definieren).
(Ich vermute also, dass bestimmte Anwendungsfälle dafür tatsächlich eine andere Sprachkonstruktion erfordern - nicht nur eine Variable. Und viele andere verwandte Anwendungsfälle wurden zuvor als Thema von #1075 betrachtet).

In vielen Fällen wird es aufgrund der faulen Bewertung nicht so funktionieren, wie Sie es erwarten
Ich vermute, dass bestimmte Anwendungsfälle dafür tatsächlich eine andere Sprachkonstruktion erfordern - nicht nur eine Variable

Sie benötigen diese spezielle Sprachkonstruktion, um den Selektorkontext an dem Punkt zu erfassen, an dem er definiert wird, und nicht an dem Punkt, an dem er durch die Auswertung der Variablen aufgerufen wird, der er zugewiesen ist. Die Auswertung sollte nur den Kontext ausgeben, der an der Definitionsstelle erfasst wurde.

Nicht viel anders als das Nachschlagen von Variablen durch Schließen, aber ja; es erfordert ein spezielles Sprachkonstrukt und keine Funktion.

@rjgotten

Ja, ich denke, wir haben vorhin über eine Pseudofunktion von selector (Pseudo, weil eine normale Funktionsanalyse sowieso nicht all diese selektorspezifischen Kombinatoren verarbeiten kann) und dann, weil es Pseudofunktion ist (dh ein dedizierter Typ wie Url ) wäre es kein Problem, den Definitionskontext in ihn hineinzuziehen (wenn ich mich richtig erinnere, machen DRs genau so).
So etwas wie <strong i="10">@foo</strong>: selector(&); könnte einen Trick machen, denke ich. Doch dann taucht ein nächstes kleines Problem auf:

a {
    <strong i="13">@var</strong>: selector(x, #y & .z);

    b {
        @{var} { // ? is it regular & or "saved-context-&" ?
            // ...
        }
    }
}

Es kann also möglicherweise einen anderen Operator/Schlüsselwort als & erfordern. (Oder vielleicht nur eine dedizierte Pseudofunktion, zB current-selector() ... Hmm, das bringt mich jetzt zu einer Idee, einen generischen PseudoFunction Typ zu codieren, um die API jedes kleinen Leckerbissens nicht zu verschmutzen, autsch! :).

Ich weiß, es gibt ein allgemeines Zögern, der Sprache neue Dinge hinzuzufügen, aber ein Selektorbezeichner könnte praktisch sein. Ich mag | , obwohl es Teil der CSS-Selektorsyntax @namespace . Es scheint jedoch nicht erlaubt zu sein, dass | einen Selektor _starten_ darf, daher sollte es nicht zu Konflikten kommen. Ich benutze es, weil es mich an den "absoluten Wert" von Math erinnert, der vage angemessen erscheint, und weil es einfach ist. Nur ein Gedanke, um Gespräche anzuregen.

a {
  <strong i="10">@var</strong>: |x, #y & .z|; // starting w/ `|` means selector, in current context, ended w/ another `|`
  b {
    @{var} {
      //...
    }
  }
}

(Tatsächlich könnte es verwendet werden, um festzulegen, dass _jede_ Variable sofort verarbeitet und gespeichert werden soll, oder was auch immer? Aber das fühlt sich an, als wäre es _weg_ übertrieben.)

ist es normal & oder saved-context-& ?

Ich würde sagen, der Selektorkontext sollte an der Site erfasst werden, an der die Pseudofunktion selector() aufgerufen wird, und & sollte innerhalb von _diesem_ Kontext ausgewertet werden und das Endergebnis sollte diesem neuen Typ zugewiesen werden des Selector .

Wenn _jede_ Variable, die einen Baumknoten vom Typ Selector in einen Selektor interpoliert wird, wie dies bei der Verwendung von @{var} im Beispiel der Fall ist, sollte der resultierende Selektor auf die gleiche Weise aufgebaut werden als wenn ein & Interpolator im Selektor vorhanden ist, dh ; Verbinden Sie die Selektoren nicht mit einem Präfix von einer Verschachtelungsebene aufwärts.

Der Grund dafür ist, dass beide erfasste Selektoren sind: selector() ist ein vom Benutzer erfasster Selektor, während & der immer vorhandene und erfasste 'übergeordnete' Selektor ist.

Wenn ein Benutzer dann die Interpolation eines erfassten Selector Knotens zusammen mit dem _aktuellen_ Selektorkontext benötigt, kann er dies explizit angeben. ZB & @{var} { ... }

Abschließend

a {
    <strong i="24">@var</strong>: selector(x, #y & .z);

    b {
        @{var} { ... }
    }
}

sollte erzeugen

x, #y a .z { ... }

Wohingegen

a {
    <strong i="31">@var</strong>: selector(x, #y & .z);

    b {
        & @{var} { ... }
    }
}

sollte erzeugen

a b x,
a b #y a .z { ... }

Hmm, @{var} vs. & @{var} sieht ziemlich künstlich aus, aber so funktionieren diese Dinge in Less nicht. ... { & div ... und ... { div ... waren immer gleiche Aussagen. Außerdem, ganz abgesehen davon, was soll ich tun, wenn ich a b x, #y a b .z mit x, #y * .z woanders definiert brauche?

Ich bin kein Fan von funktionsähnlichen Konstrukten für Selektoren. Ich unterstütze jedoch die Möglichkeit, geerbte Selektoren zu referenzieren, zu ändern oder zu transportieren (einer Variablen zuzuweisen und wiederzuverwenden).

Nur um sicherzustellen, dass dies eine Variation von #1075 ist (Ausrichtung auf übergeordnete Selektoren) oder in einem möglichen Konflikt mit https://github.com/less/less-meta/issues/16#issuecomment -292679320 (Zuweisung) ein einzelner Selektor für eine Variable)? Oder ist dies anders als Mixins Aliasing , weil diese eine Auswahlliste und nicht ein einzelner ausgewerteter Wähler (oder mixin), und der Ausgang ist die Auswahlliste und nicht die ausgewertete ruleset? Ich gehe davon aus, dass diese Funktion anders ist; Ich möchte nur sicherstellen, dass sich alle in die gleiche Richtung bewegen.

@matthew-dean
Es geht in der Tat um das Erfassen der eigentlichen Selektorliste, nicht um das Erfassen des ausgewerteten Regelsatzes und die Ausgabe dieser Liste zur weiteren Verwendung.

Man könnte sich vorstellen, dass eine Funktion wie extract(list,index) aktualisiert wird, um auch Selektorkomponenten aus einer Selektorliste zu extrahieren und ähnliche Verbesserungen, um die Arbeit mit Selektoren zu erleichtern, sodass Benutzer sie auf interessante Weise leicht manipulieren können. Zum Beispiel für Komponenten, die bestimmten Benennungsschemata wie BEM folgen.

ZB einen Mixin gegeben

.my-bem-component(<strong i="10">@a</strong>, @b) {
  // Component will only ever be constructed on the first selector in
  // a list, for simplicity.
  <strong i="11">@selectors</strong> : selector(&);
  <strong i="12">@selector</strong>  : extract(<strong i="13">@selectors</strong>, 1);

  // Generate a clean block name, cleared of modifiers.
  // Grabs e.g. "bar" from ".foo > .bar--baz"
  @block-name : replace(<strong i="14">@selector</strong>, "\.([^\.\s]+)--\S+$", "$1" );

  // Generate the modifier name and generate different CSS for
  // BEM classes that have one.
  // Grabs e.g. "baz" in ".foo > .bar--baz"
  @mod-name : replace(<strong i="15">@selector</strong>, "\.+--(\S+)$", "$1" );

  .generate-block();
  // When @mod-name matches <strong i="16">@selector</strong>, no replacement has
  // occured and we are infact in the situation where we have no
  // BEM modifier and generate the 'base' component.
  .generate-block() when (@mod-name = "@{selector}") {
    @{selector} {
      prop-a : @a;
    }
    @{selector}__element {
      prop-b : @b;
    }
  }

  .generate-block() when (default()) {
    @{selector} {
      prop-a : @a;
    }
    @{selector} > .@{block}__element {
      prop-b : @b;
    }
  }
}

Das folgende Weniger

.block {
  .my-bem-component(foo, bar);
}
.block--caps {
  .my-bem-component(FOO, BAR);
}

generiert CSS

.block {
  prop-a : foo;
}
.block__element {
 prop-b : bar;
}
.block--caps {
  prop-a : FOO;
}
.block--caps > .block__element {
  prop-b : BAR;
}

Sass hat das, afaik, schon lange und es gibt zahlreiche Beispiele, wie diese Technik sehr geschickt eingesetzt wird. In Codefactorys wie in meinem Beispiel oder für andere Zwecke.

Wie für:

möglicher Konflikt mit less/less-meta#16 (Kommentar) (Zuweisung eines einzelnen Selektors zu einer Variablen)

Ich persönlich gehe von folgendem Verhalten aus:
"Triviale" Selektorwerte (zB .mixin , .ns.mixin , #foo .bar , baz usw., zum Glück deckt dies alles ab, was als Mixin/Funktion verwendet/definiert werden kann ) werden einer Variablen direkt zugewiesen (oder als Parameter an eine Funktion übergeben). Dh das haben wir eigentlich schon:

<strong i="15">@var</strong>: .ns.mixin; // OK, its just Anonymous value (representing an arbitrary identifier) 
function(.mixin); // error: TODO 

^Dies hat (im Wesentlichen) überhaupt nichts mit Selektoren zu tun - diese Werte werden (versucht) in ein Selektorformat umgewandelt (um ein Mixin zu suchen) nur, wenn wir versuchen, sie mit @var(...) aufzurufen/auszuwerten oder @var[...] Anweisungen
(Im Allgemeinen wäre die logische Konvention, zu vergessen, dass Mixin-Bezeichner (intern als) Selektoren sind, aber sie immer als Bezeichner mit nur einem Punkt oder # Präfix zu betrachten, und Dinge wie .ns > .mixin to verblassen schließlich als überflüssig und nutzlos :)

Während komplexe oder "echte" Selektoren aufgrund der Syntax/Parser-Mehrdeutigkeit eine Pseudofunktion selector erfordern . Dh Dinge wie:

  • <strong i="29">@var</strong>:foo>bar <- Selektor und (möglicherweise) ein logischer Ausdruck
  • <strong i="32">@var</strong>:.1+.2; <- Rechenausdruck und gültiger Less- Selektor
    (usw. erinnern Sie sich einfach an alle spezifischen Selektorsymbole - fast jedes kollidiert mit etwas in einem Wert-Parsing-Kontext, und dies wird noch dramatischer, wenn die obigen Werte möglicherweise als Parameter an eine Funktion / ein Mixin übergeben werden, z. B. Folgendes ist einfach unmöglich ohne selector() :
    less: some-function(abc, selector(#foo .is :not(> bar)[baz="qux"], abc), selector(bla), 42); // ^ remove `selector()` and try to parse

Ich bin kein Fan von funktionsähnlichen Konstrukten für Selektoren.

Zusammenfassend ist die Pseudofunktion selector nur notwendig, um alle aktuellen und potenziellen Syntax- und Semantikkonflikte ein für alle Mal auszuschließen. Ich bezweifle also, dass wir hier wirklich zu viele Optionen haben (Wert- und Selektor-Parsing-Kontexte müssen nur irgendwie getrennt werden).


(Alle tun oben nicht bedeuten , dass ein Rückgabewert von selector() kann nicht als aufrufbare Einheit verwendet werden , zB @var() , es könnte wahrscheinlich - aber das wäre nur unnötig / nutzlos, so ist es kaum wert zu Mühe).

@rjgotten

Man könnte sich vorstellen eine Funktion wie extract(list,index) zu aktualisieren um auch Selektoren extrahieren zu können

Natürlich könnten wir Funktionen so anpassen, dass sie mit Strings arbeiten, vorausgesetzt, dass ein solcher String einen Selektor enthält, aber das bedeutet, dass jede solche Funktion (nicht nur extract ) aktualisiert/angepasst/modifiziert werden muss. Der umgekehrte Ansatz wäre effizienter / weniger belastend. Dh es ist entweder eine dedizierte selector-string->values Konvertierungsfunktion ODER gibt sogar die richtige Struktur der Knoten direkt durch selector (in beiden Fällen ist der schwierigste Teil das Packen/Entpacken von Selektorkombinatoren bei jeder Verwendung -case kann eine andere Darstellung bevorzugen).

(Beachten Sie, dass die Selektor-Interpolationsfunktion selbst @{var} am Ende sowieso in ein richtiges Format konvertieren muss, sodass es nicht wirklich wichtig ist, in welchem ​​​​Format der Wert dieser Variablen ankommt – entweder ob es sich um eine Zeichenfolge, anonym oder was auch immer handelt Knotenstruktur - der größte Teil der Konvertierungstricks bleibt gleich).

@block-name : replace(<strong i="17">@selector</strong>, "\.([^\.\s]+)--\S+$", "$1" );

Um ehrlich zu sein, sieht dies wie eine Reinkarnation von "Inline-JavaScript und LessHat-like Hackery" aus, kann nicht verbieten, wird aber aggressiv dagegen werben.
(Abgesehen davon, dass das Beispiel ziemlich unglücklich ist <- zähle die Zeilen) Ich würde eher etwas less-plugin-bem-selectors vorschlagen (wo man einfach eine get-block-name Funktion haben kann, übrigens auch ohne die & Feature) statt solch hässlicher Regexes (der Ansatz "Verwendung eines CSS-Präprozessors als willkürlichen Textprozessor" wird schließlich am Ende stark an PostCSS-ähnlichem Zeug verlieren).

Und zurück zu & vs. context-saving-& , bisher habe ich leider keine bessere Idee als entweder ein dediziertes Flag für die Funktion, zB selector(..., lazy or not) , oder sogar zwei separate Funktionen. Oder verwenden Sie other-than-&-keyword (zB ). Ich kann einfach keine sichere Methode sehen, um die Mehrdeutigkeit am Bewertungspunkt automatisch aufzulösen.

Ich würde eher etwas less-plugin-bem-selectors vorschlagen

Absolut. Die auf Regex basierende Extraktion sollte nur ein Beispiel liefern, das keine benutzerdefinierten Funktionen beinhaltete. ;)

Ich bin kein Fan von funktionsähnlichen Konstrukten für Selektoren.

Außerdem, wenn Sie nur meinen, wie es aussieht ... Es könnte natürlich eine andere Konstruktion sein, zB ⁞#foo:not(.bar)⁞ , aber Sie wissen, dass wir bereits keine freien Symbole mehr haben. Die Pseudofunktionssyntax wird also nur vorgeschlagen, weil wir mit url sowieso bereits ein solches Konzept haben (daher muss man sich keine Gedanken machen, was ein neues Konzept kaputt machen könnte oder wird).

Jetzt der lustige Teil.

Ich habe eine schnelle und schmutzige Plugin-Implementierung der current-selector Funktion erstellt (nur um zu sehen, wie aufgebläht es sein könnte, in der Erwartung, dass es natürlich aufgrund der var-Lazy-Evaluation nicht sehr nützlich sein kann) und weißt du was? Dieses grundlegende Beispiel:

div {
    <strong i="9">@x</strong>: current-selector();
    span {
        r: @x; // -> div
    }
}

ergibt r: div :)
Keine Ahnung, welcher Teil des Compilercodes dieses spezielle Verhalten handhabt, aber hier ist ein fortgeschritteneres Beispiel, um die Magie zu veranschaulichen:

div {
    <strong i="15">@x</strong>: current-selector();     // [1]
    <strong i="16">@y</strong>: current-selector() @v;  // [2]
    <strong i="17">@z</strong>: current-selector(@v);   // [3]
    <strong i="18">@v</strong>: whatever;
    span {
        1: @x; // div
        2: @y; // div span
        3: @z; // div span
        4: current-selector();  // [4] div span
    }
}

Dort werden nur die [2] und [3] Anweisungen zweimal aufgerufen (also eigentlich faul ausgewertet), während die [1] nicht (anscheinend weil der Wert aber keine Variablen enthält) Nochmals, ich weiß nicht, ob dies beabsichtigt oder nur ein Nebeneffekt von Caching ist, oder es könnte ein glücklicher Fehler in meinem Code sein - zum Beispiel kann diese Zeile einen solchen Nebeneffekt für dieses Caching auslösen - aber dann ist es nicht klar warum es von zusätzlichen Variablen beeinflusst wird - dh mehr Forschung erforderlich).


Das heißt, eine Plugin-basierte Version von context-saving-& scheint möglich zu sein (außer dass Sie natürlich anstelle von <strong i="29">@var</strong>: & etwas wie <strong i="31">@var</strong>: current-selector() ). keine Parameter haben, sonst wird es faul ausgewertet (wenn eine Variable übergeben wird) - das ist traurig, da ich ursprünglich vier geplant hatte :).
Ziemlich missbräuchlich, könnte aber als Workaround/Polyfill dienen. Ein realeres Beispiel funktioniert auch wie gewünscht:

div#zoo {
    <strong i="35">@x</strong>: current-selector();
    span {
        <strong i="36">@y</strong>: replace(<strong i="37">@x</strong>, div, body);
        r: @y; // OK, body#zoo
        @{y} { 
        // ^ not very useful this way (except maybe bem stuff) since you can't remove div
            color: red;
        }
    }
}

dh nachfolgende Variablenzuweisungen / Funktionsaufrufe haben keinen Einfluss auf den Auswertungspunkt der Ausgangsvariablen.

@sieben-phasen-max
Liebe es.

Auch wenn Lazy-Evaluation derzeit einen Strich durch die Rechnung macht, wenn ein Parameterargument vorhanden ist, ist _das_ vermutlich etwas, das für eine 'echte' Implementierung umgangen werden kann.

Außerdem, wenn Sie nur meinen, wie es aussieht... Es könnte natürlich eine andere Konstruktion sein, zB ⁞# foo:not (.bar)⁞, aber Sie wissen, dass wir bereits

Meinetwegen. Ich habe mich nicht wirklich damit beschäftigt, was die Verwendung angeht, und ich habe auch keine besseren Ideen. Ich denke, das schien etwas Besonderes zu sein, aber vielleicht auch nicht. Ich weiß, dass es irgendwann eine Diskussion über $() , aber am Ende haben wir uns $ angeeignet. Übrigens, wäre es nicht selectors() und nicht selector() ? Kann es (wie das & ) nicht beliebig viele Selektoren enthalten?

Und es scheint, dass selector(&) sinnvoller ist als current-selector() . Das heißt: "Erstelle eine Selektorliste aus einem X-Objekt, sei es & oder ein String". Was auch immer die endgültige Syntax ist, es scheint & als Argument zu benötigen.

Und es scheint, dass selector(&) sinnvoller ist als current-selector()

Das sind verschiedene Dinge. current-selector ist nur eine Funktionsvariante von & (da letztere vom Parser nicht unterstützt wird). Während selector(...) der Patch für den Parser ist, um einen beliebigen Selektor (einschließlich & ) zu unterstützen.


Was selectors - nun, das ist es. Aber da es 99% der Anwendungsfälle für einzelne Selektoren sind, würde eine Pluralform für die meisten Benutzer weniger offensichtlich klingen (in den meisten benennen sie normalerweise h1, h2, h3 {} als Selektor und sprechen immer wieder von Weniger übergeordneter Selektor (sogar wenn es Selektor s ist ) :) Also warum die Mühe machen?

Ah okay.

@matthew-dean
Plural- und Singularform sind für jeden austauschbar, außer für die CSS-Spezifikationsautoren. In der Tat, machen Sie das: für jeden, einschließlich der Spezifikationsautoren, da sogar die CSS-Spezifikationen manchmal der vertauschten Verwendung der Singular- und Pluralform zum Opfer fallen.

Ziemlich urkomisch; der Pluralbegriff 'Selektoren' ist nicht einmal die offizielle Art, eine durch Kommas getrennte Menge zu bezeichnen. Die absolut korrekte Terminologie für die Pluralform ist meiner Meinung nach eine _Auswahlliste_.

Sie können also sehen, wie tief dieser mehrdeutige Verweis wirklich verwurzelt ist.

Die absolut korrekte Terminologie für die Pluralform ist meiner Meinung nach eine Auswahlliste.

Ja, ich habe gestern auch w3c durchsucht, es ist "Gruppe von Selektoren", "eine Liste von Selektoren" usw habe dort :) Nur das Formular "Selektoren" wird dort meistens verwendet, um die Sache mit den "Selektortypen" zu beschreiben.

"Ein Selektor ist eine Kette von einer oder mehreren Sequenzen einfacher Selektoren, die durch Kombinatoren getrennt sind"

Und für alle, die denken, dass sich das auf durch Kommas getrennte Listen beziehen könnte: Das ist es nicht. Die vollständige Form dieses Zitats sollte lauten: "ein _komplexer_ Selektor ist eine Kette von einer oder mehreren Folgen einfacher Selektoren, die durch Kombinatoren getrennt sind."

Die CSS-Spezifikationen haben ein weiteres Problem, bei dem die verallgemeinerte Form von "Selektor" hauptsächlich verwendet wird, um auf das zu verweisen, was die Spezifikationen offiziell _komplexe Selektoren_ nennen. Komplexe Selektoren sind einfache Selektoren, zB tag ; #id ; .class ; [attr] ; etc. , verkettet über Kombinatoren, zB > ; + ; ~ usw.

Etwas wie ul > li wird als komplexer Selektor bezeichnet.


WARNUNG, das Folgende wird ein bisschen geredet:

Die CSS-Spezifikationen sind leider ein Sumpf inkonsistenter und schlecht benannter Terminologie. Je weiter man zurückgeht, desto schlimmer wird es. Hilft nicht, dass viele CSS3-Module immer wieder auf CSS 2.1-Module verweisen oder dass neue CSS3-Module durch wörtliches Kopieren ihrer alten CSS 2.1-Dokumentation spezifiziert wurden. Die Spezifikationen für Selektoren und das visuelle Formatierungsmodell sind jedoch die schlimmsten Übeltäter; so viel mehrdeutige, ähnlich klingende oder schlicht schlecht benannte Terminologie.

Nehmen wir zum Beispiel etwas weit weniger Triviales als ul > li , wie [*|attr^="value" i] . Letzteres wird technisch als einfacher Selektor klassifiziert. (Ja wirklich.)

Ich musste vor einigen Jahren auch einmal versuchen, einem meiner eher designorientierten Kollegen Teile der letztgenannten Modellspezifikation für die visuelle Formatierung zu erklären. Ich glaube, ein paar Sicherungen sind in _beiden_ unseren Gehirnen durchgebrannt, während wir die Passagen durchgegangen sind, die das Konzept der Lineboxen behandeln, und das war nicht einmal das Schlimmste daran. (Versuchen Sie, das magische la-la-land zu betreten, das das Tabellenformatierungsmodell ist, wenn Sie wenig Wert auf Ihren Verstand legen.)

Vielfältige Freuden an der Dokumentation von Open-Source-Projekten...

Nehmen wir zum Beispiel etwas viel weniger Triviales als ul > li , wie [*|attr^="value" i] . Letzteres wird technisch als einfacher Selektor klassifiziert

Das macht für mich tatsächlich Sinn, lol, nur weil es keinen Kombinator verwendet. Es folgt der Definition genau. Nur weil es viele Symbole verwendet, wird es nicht "komplexer". ul > li ist komplex, weil es zwei Sätze von Abfragen beinhaltet, dh Abfragen nach allen Elementen, die mit li übereinstimmen und dann den Baum von jedem nach oben durchlaufen, um zu bestimmen, welche in einem ul . Letztere testet einzelne Elemente nur einmal. Es ist eine Abfrage, also ein einfacher Selektor.

der Pluralbegriff 'Selektoren' ist nicht einmal die offizielle Art, eine durch Kommas getrennte Menge zu bezeichnen. Die absolut korrekte Terminologie für die Pluralform ist meiner Meinung nach eine Auswahlliste.

Stimmt, du hast recht. "Selektoren" sind eigentlich nur die definierten Bits, mit denen Sie Elemente auswählen können, aber ul > li > .title ist ein "Selektor" Singular. Also denke ich, dass selector() in der Tat vielleicht semantisch näher ist.

@sieben-phasen-max

Ich bin gerade auf ein weiteres kleines Problem mit der Quick-n-Dirty-Plugin-Funktion gestoßen: Sie behandelt den Zugriff von einem Namespace-Mixin nicht korrekt. Namensräume sind ein regulärer Rahmen vom Typ Ruleset und daher wird ihr Name in die Selektoren eingefügt.

Eine echte Implementierung sollte wahrscheinlich auch diesen Fall abdecken.


[BEARBEITEN]
Der Trick, damit es funktioniert, besteht darin, zu überprüfen, ob einer der Frames im Stapel des Funktionskontexts ein MixinDefinition und wenn er _ist_, überspringen Sie die nächsten x Frames auf diesem Stapel, wobei x entspricht der Anzahl der Frames auf dem Stapel des MixinDefinition .

(Im Grunde überspringt dies die 'Schließungs'-Frames, die dem Stack hinzugefügt werden, wenn ein MixinCall MixinDefinition ausführt.)

Das Etikett "sale" wurde entfernt. Dies ist immer noch ein gutes Thema, das es zu erkunden gilt.

Vielleicht ist current-selector() nicht so schlimm. Obwohl es, um es klar zu sagen, tatsächlich current-selectors() . Aber das ist noch ein bisschen ausführlich. Ich denke, ich wäre eher dafür, wenn wir uns einen Funktionsnamen für "Erfassen &" einfallen lassen könnten, der prägnanter ist.

Funktionsname für "Erfassen &", das ist prägnanter.

Nennen Sie es einfach &() . Es ist konzeptionell nichts anderes als ein Getter für das, was in & steckt.
Z.B

.rule {
  <strong i="11">@selectors</strong> : &();
}

🤔
Ja, das sollte in Ordnung sein. Irgendwelche Einwände?

Ich werde versuchen, zusammenzufassen, um zu sehen, ob ich die vorgeschlagene Funktion verstehe:

Die neue Funktion &() zurück, was & im aktuellen Kontext ausgeben würde, was dies ermöglicht.

.component { // I only write "component" once!  Much concise, such DRY!
  <strong i="9">@this</strong>: &();

  /* base styles */

  &_child {
    /* styles for the child */
  }

  &-variant { // component-variant styles all together, and inside the `.component` block
    /* nothing too schmancy so far */
    @{this}_child {
      /* IT'S MAGIC! */
    }
  }
}

Und das alles würde dies ausgeben.

.component {
  /* base styles */
}
.component_child {
  /* styles for the child */
}
.component-variant {
  /* nothing too schmancy so far */
}
.component-variant .component_child {
  /* IT'S MAGIC! */
}

Denn das ist großartig und ich liebe es.

Wenn ich mehr darüber nachdenke, denke ich, dass das überzeugendste für mich (nach einem ersten Durchgang; stoppen Sie mich, wenn ich zu verrückt werde) die Möglichkeit eines standardisierten Komponenten-"Block"-Stils (Regelsatz) wäre. Im Grunde würde ich fast hoffen, dass die Funktion anstelle eines einfachen gespeicherten Selektor-String-Werts auf _" & , aber im Geltungsbereich wurde die Variable in"_ definiert, was diesen Authoring-Stil ermöglichen würde für eine Komponente (ich nenne das Verhalten A ):

.component{ <strong i="8">@this</strong>:&();
  /* default styles */
  @{this}_child {
  // ↑ The crucial difference: `@{this}` here behaves _like `&`_, **NOT** like `.component`
    /* child default styles */
  }
}

Dann könnte ich sagen "verwende @this überall statt & ".

Meine einzige Sorge wäre der Flip-Fall (den ich Verhalten B nenne), aber mir fällt kein zwingender Fall ein, in dem ich dieses Verhalten haben möchte. Das heißt, ich kann nicht sehen, warum jemand dies tun möchte.

.foo { <strong i="16">@and</strong>: &();
  @{and} {
    /*stuff meant to live under selector `.foo.foo` */
  }
}

Denn der derzeitige Weg, dies zu erreichen, ist _viel_ prägnanter (und auch lesbar, sobald & in Ihrem Vokabular klar ist).

.foo {
  && {
    /*stuff meant to live under selector `.foo.foo` */
  }
}

Gibt es einen zwingenden Fall (abgesehen von Schwierigkeiten bei der Implementierung) für Verhalten B gegenüber Verhalten A?

Dies ist nur eine der Fragen, die meiner Meinung nach vor Beginn der Arbeit beantwortet werden sollten.


TL;DR: Meine Stimme ist dafür, dass &() dynamisch ist, was im Wesentlichen _" & , aber als wäre es hier verschachtelt statt tiefer"_, anstatt ein statisches _" zurückzugeben, der Wert von & jetzt."_

@calvinjuarez Ihre Beispiele sind etwas verwirrend, weil Sie nicht Ihre erwartete Ausgabe schreiben, daher scheinen sie etwas im Bereich des Theoretischen zu liegen, aber im Grunde:

.component{
  <strong i="7">@this</strong>: &();  // <strong i="8">@this</strong> is now assigned the value of `.component`
  @{this}_child { a: b; } // this variable, when evaluated, forms the selector .component_child
}
// therefore this output is:
.component .component_child {
  a: b;
}

bedeutet im Wesentlichen "&, aber als wäre es hier verschachtelt statt tiefer", anstatt ein statisches "Der Wert von & im Moment" zurückzugeben.

Ich verstehe wirklich nicht, was das bedeutet.

Eine andere Möglichkeit, darüber nachzudenken. Dies:

.component {
  <strong i="6">@this</strong>: &()
}

Entspricht dem Schreiben:

.component {
  <strong i="10">@this</strong>: .component;
}

@matthew-dean

Ja. Aber denken Sie durch die Linse von Mixins, wobei &() den Selektorkontext des Mixin-Aufrufers erfassen würde.

Es ermöglicht das Schreiben von Mixin-basierten Komponenten, bei denen die Autoren selbst auf natürliche Weise frei über die Wurzel des Klassennamens entscheiden können. zB gegeben

.my-button {
  #buttons.base();
  #buttons.size( ... );
  #buttons.inset-icon-support( left right );
}

.my-button--wide {
  #buttons.size( ... )
}

.my-button--condensed {
  #buttons.size( ... )
}

die dort verwendeten Mixins könnten die Klasse über &() einlesen und entsprechend in ihre Ausgabe einarbeiten. Beispielsweise könnte der für die zweite und dritte Regel erfasste Selektor die BEM-Syntax zerlegen, um die Basisblockklasse zu erhalten, die verwendet werden könnte, um Überschreibungen für Selektoren verschachtelter Elemente zu generieren.

Das ist; es könnte verwendet werden, um einen Selektor wie .my-button--wide > .my-button__text zu generieren, ohne dass irgendwelche Selektornamen als Parameter übergeben werden müssen. Nur aus dem Kontext der Angerufenen-Auswahl.


Mixin-basierte _Komponentenfabriken_ wie diese vermeiden viele der Alles-oder-nichts-auf-der-Weg-oder-der-Autobahn-Probleme, die Sie bei der Verwendung von Styling-Frameworks bekommen. Sie ermöglichen es Ihnen, das Framework zu registrieren, aber granular auszuwählen, welche Komponenten Sie tatsächlich einbinden möchten und unter welchem ​​Namen.

@rjgotten

die dort verwendeten Mixins könnten die Klasse über &() auslesen und entsprechend in ihre Ausgabe einarbeiten. Beispielsweise könnte der für die zweite und dritte Regel erfasste Selektor die BEM-Syntax zerlegen, um die Basisblockklasse zu erhalten, die verwendet werden könnte, um Überschreibungen für Selektoren verschachtelter Elemente zu generieren.

Ja, ich verstehe. Es ist wahrscheinlich am nützlichsten in Mixins. Ich bekomme definitiv den Nutzen von &() gegenüber der Verwendung des direkten Selektornamens. Ich wollte nur versuchen, den Wert von &() im gegebenen Beispiel zu verdeutlichen.

Um noch weiter zu gehen, denke ich, dass es eine gute syntaktische Lösung ist, und ich persönlich würde ein 👍 dafür geben, mit der Implementierung von &() fortzufahren, wenn jemand dies übernehmen möchte.

@matthew-dean

Ihre Beispiele sind etwas verwirrend, weil Sie nicht die erwartete Ausgabe schreiben

Hoppla, Entschuldigung. Ich werde es richtig wiedergeben. Ich habe das Gefühl, dass &() eine stärkere Funktion wäre, wenn das Less hier zum CSS unten kompiliert würde.

.component { <strong i="10">@this</strong>:&();
  /* default styles */
  @{this}_child {
  // ↑ The crucial difference: `@{this}` here behaves _like `&`_, **NOT** like `.component`
  // (since it's in the same rule block and scope level).
    /* child default styles */
  }
}
.component {
  /* default styles */
}
.component_child {
  /* child default styles */
}

Wenn sich <strong i="15">@this</strong>:&(); in diesem Fall genauso verhält wie <strong i="17">@this</strong>:.component; , delegieren wir diese Funktion _nur_ als Dienstprogramm innerhalb von Mixins, aber ich denke, es hat mehr zu bieten.

bedeutet im Wesentlichen "&, aber als wäre es hier verschachtelt statt tiefer", anstatt ein statisches "Der Wert von & im Moment" zurückzugeben.

Ich verstehe wirklich nicht, was das bedeutet.

Das bedeutet, dass ich denke, dass .thing{ & {} } und .thing{ <strong i="11">@amp</strong>:&(); @{amp} {} } dieselbe Ausgabe erzeugen sollten.

Das bedeutet praktischer, dass Sie für einfaches BEM kein Mixin schreiben müssen, sondern es inline definieren können. Zurück zu einem meiner älteren Beispiele:

_komponenten.weniger_

.component { // I only write "component" once!  Much concise, such DRY!
  <strong i="16">@this</strong>: &();

  /* base styles */

  @{this}_child {
    /* styles for the child */
  }

  @{this}-variant { // component-variant styles all together, and inside the `.component` block
    /* nothing too schmancy so far */
    @{this}_child {
      /* IT'S MAGIC! */
    }
  }
}

↓↓↓

_Komponente.css_

.component {
  /* base styles */
}
.component_child {
  /* styles for the child */
}
.component-variant {
  /* nothing too schmancy so far */
}
.component-variant .component_child {
  /* IT'S MAGIC! */
}

Der Vorteil: Sie müssen Ihr Team nicht fragen, ob es & oder @{this} meint. Sie sagen einfach "Verwenden Sie einfach überall @{this} ".

Es würde eine Mixin-Definition einer Komponentenfabrik auch intern konsistenter machen.

_hypothetischer-button-mixin.less_

#button () {
  .size(large) { <strong i="7">@button</strong>: &();
    @{button} { // same scope, so it behaves _exactly_ like `&`.
      font-size: 1.8rem;
    }
    @{button}-primary { // same scope, so it behaves _exactly_ like `&`.
      border-width: 5px;
      @{button}_icon { // nested scope, behaves like the parent selector at the mixin call (.btn).
        height: 1.8rem;
        width:  1.8rem;
      }
    }
  }
}
// ...

_hypothetische-stile.weniger_

.btn {
  #button.size(large);
}

_hypothetische-stile.css_

.btn {
  font-size: 1.8rem;
}
.btn-primary {
  border-width: 5px;
}
.btn-primary .btn_icon {
  height: 1.8rem;
  width:  1.8rem;
}

Das bedeutet, dass ich denke, dass .thing{ & {} } und .thing{ @amp :&(); @{amp} {} } sollte dieselbe Ausgabe erzeugen.

Ja, ich denke, wir sagen dasselbe, aber lassen Sie es mich mit diesem Beispiel bestätigen. So sehe ich diese Funktion im Vergleich zu direkt & .

.mixin() {
  <strong i="10">@this</strong>: &();
  .a {
    .b @{this} { c: d; }
  }
}
.component {
  .mixin();
}

// outputs:
.component .a .b .component {
  c: d;
}

Wohingegen:

.mixin() {
  .a {
    .b & { c: d; }
  }
}

Würde produzieren:

.b .component .a {
  c: d;
}

@calvinjuarez Ich glaube, ich war verwirrt, weil ich glaube, niemand hat etwas anderes als Ihr Beispiel vorgeschlagen. &() wäre im Wesentlichen so, als würde this.selectors.toCSS() an diesem Ort ausgewertet ( nicht wirklich, aber nur zur Veranschaulichung .... eigentlich könnte das der schnellste Weg sein). Und dann fügen Sie diese Zeichenfolge an anderen Stellen ein, um sie als Selektoren erneut auszuwerten.

@matthew-dean
Es wäre sogar noch _mehr_ genial, wenn es die Selektorliste als eine tatsächliche Liste von Selektoren verfügbar machen würde, einschließlich des besonderen Verhaltens zum Erweitern von Selektoren basierend auf allen Listenmitgliedern.

Habe zB

.a, .b {
  <strong i="8">@this</strong> : &();

  @{this} {
    c : d;  
  }
}

Ausgang

.a .a,
.a .b,
.b. .a,
.a .b {
  c : d
}

genau wie das native & es

Ja, genau das würde es tun. In 3.5 führen alle in Selektoren ausgewerteten Variablen dazu, dass die gesamte Selektorliste als neue Selektorliste neu geparst wird. Also ja, das würde wie erwartet funktionieren. Es ist eigentlich ganz einfach wegen einiger neuer PRs, die ich gemacht habe.

Am 7. Juli 2018 um 10:34 Uhr schrieb rjgotten [email protected] :

@matthew-dean
Es wäre sogar noch großartiger, wenn die Selektorliste als tatsächliche Liste von Selektoren verfügbar gemacht würde, einschließlich des besonderen Verhaltens zum Erweitern von Selektoren basierend auf allen Listenmitgliedern.

Habe zB

.a, .b {
@dies : &();

@{Dies} {
CD;
}
}
Ausgang

.a .a,
.a .b,
.B. .ein,
.a .b {
CD
}
genau wie die Einheimischen und würden.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub an oder schalten Sie den Thread stumm.

.component{
 <strong i="6">@this</strong>: &();  // <strong i="7">@this</strong> is now assigned the value of `.component`
 @{this}_child { a: b; } // this variable, when evaluated, forms the selector .component_child
}
// therefore this output is:
.component .component_child {
 a: b;
}

Das zusätzliche .component ist das, wogegen ich argumentiere. Ich schlage vor, es sollte so funktionieren:

less .component{ <strong i="12">@this</strong>: &(); // <strong i="13">@this</strong> is now assigned the value of `.component < &` @{this}_child { a: b; } // this variable evaluates like `&_child` } // therefore this output is: .component_child { // < Note: `.component_child` !== `.component .component_child` a: b; }

Es scheint, als würde die Funktion jedoch in eine andere Richtung gehen. Wollte nur meine Position klarstellen.

Ich schlage vor, es sollte so funktionieren:

Dh wenn es in einem Selektor ein Substitutionstoken gibt, das eine _Selektorliste_ anstelle einer einfachen _string_ ist, dann verhält sich das Substitutionstoken genauso, als ob & angegeben wäre und es _deaktiviert_ die normale Selektorverkettung, die sich aus der Verschachtelung ergibt.

Wenn &() einen Knotentyp ausgeben würde, der ihn als tatsächliche Selektorliste identifizierbar macht, wäre dieses Verhalten meiner Meinung nach vergleichsweise einfach zu erreichen.

In der Tat, wenn es einen dedizierten Knotentyp ausgeben würde, könnte dies später auch die Erstellung von Plugin-Funktionen zum _Manipulieren_ der erfassten Selektorliste unterstützen.

Für mich hört sich das so an, als würde &() zu viel Arbeit auf einmal machen. Wenn Sie möchten, dass Selektoren in einer Variablen gespeichert werden, ist das eine Sache, aber wenn diese Variable die Selektorverkettung aufgrund ihres _Inhalts_ deaktiviert, wäre die Syntax unklar. Diese Variable könnte von irgendwoher kommen (zB von einem Mixin übergeben) und die Auswahlliste könnte durch einfache Variablenzuweisung generiert werden. Das heißt, aus der Verwendung von Variablen ist nicht ersichtlich, dass basierend auf dem Inhalt der Variablen ein anderes Verkettungsverhalten auftreten würde.

Ich denke, wenn Sie die Verkettung deaktivieren möchten, müssen Sie angeben, dass Sie das implizite & durch einen anderen Wert ersetzen möchten, wie (verzeihen Sie die Formatierung, ich bin auf meinem Telefon) -

.Komponente {
@var : &();
&(@var)_child {} // oder eine solche „Ersatz von &“-Syntax
}

Ich verstehe also, warum das Ergebnis wünschenswert ist, aber IMO können wir das Zusammenführungsverhalten von Variablen nicht einfach "magisch umschalten", basierend darauf, woher die Auswahlliste stammt. Dies erfordert zwei unterschiedliche Funktionen.

ooh... ich mag das &(...) Ding eigentlich...

Ha, wirklich? Glauben Sie nicht, dass es zu einer semantischen Verwechslung von &() (Erfassung von Selektoren aus &) und &(@arg) (Ersetzen von & durch Selektoren) kommen würde?

Sie sollten erwägen, sie nicht zu mischen, da jemand & durch einen leeren Selektor ersetzen möchte, um ihn im Wesentlichen zu verwerfen. (Um ein Kind an der Wurzel zu platzieren.) Obwohl es vielleicht &(“”) .child sein könnte?

Ich weiß nicht, es verdient einige Überlegungen / Überlegungen.

Außerdem gibt es, wie im Thread „Elternselektoren sollten Ziele haben“ erwähnt, Anwendungsfälle für das Ersetzen bestimmter Teile des geerbten Selektors (oder vollständig). In dieser Ausgabe sollte es nur um das Erfassen von &

Um diesen Kreis zu schließen, habe ich hier die Änderung von & mit einem funktionsähnlichen Konstrukt erwähnt. - https://github.com/less/less.js/issues/1075#issuecomment -397697714

Daher würde ich es vorziehen, wenn die Diskussion darüber, "wie / ob die Vererbung von & geändert werden soll", im übergeordneten Selektor-Thread verbleibt, und in diesem Thread geht es darum, ob <strong i="9">@var</strong>: &() geeignet ist, die In zu erfassen -Platziere den & Selektor auf eine Variable. Was meiner Meinung nach trotz des anderen Threads immer noch in Ordnung zu sein scheint. Ich bin mir nicht sicher, ob es eine Möglichkeit gibt, beides zu tun oder nicht.

Ich versuche das zu tun

.html, .css, .js, .php, .mysql, .jquery, .txt, .java {
    <strong i="6">@html</strong>: '\f2d0';
    <strong i="7">@css</strong>: '\f034';
    <strong i="8">@js</strong>: '\f121';
    <strong i="9">@php</strong>: '\f120';
    <strong i="10">@mysql</strong>: '\f1c0';
    <strong i="11">@jquery</strong>: '\f78c';
    <strong i="12">@java</strong>: '\f11b';
    <strong i="13">@txt</strong>: '\f15c';
    &:before {
        content+_: @&;
    }
}

aber das wird nicht funktionieren, bis dies implementiert ist

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen