Less.js: حفظ المحدد لمتغير

تم إنشاؤها على ٢٠ أبريل ٢٠١٧  ·  50تعليقات  ·  مصدر: less/less.js

لدينا هذا الحل:

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

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

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

أقترح إضافة ميزة: كتابة <strong i="9">@r</strong>: &; بدلاً من <strong i="11">@r</strong>: ~".selector"; للحصول على المحدد الحالي وحفظه في أي متغير.

أمثلة:

// 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

ال 50 كومينتر

من الغريب أنني كنت متأكدًا تمامًا من وجود هذا الطلب بالفعل. يبدو أنه ليس كذلك.
(على الرغم من أنه من الواضح أن الفكرة ظهرت في العديد من التذاكر من قبل: # 1174 ، https://github.com/less/less.js/issues/1075#issuecomment-16891103 إلخ.)
لذا فليكن على ما أظن.


راجع للشغل ، فقط في حالة (ولجمع بعض حالات الاستخدام للتفكير في تعارضات impl./syntax محتملة):
كيف انت ذاهب لاستخدامه؟ أظن أنه في كثير من الحالات لن يعمل بالطريقة التي تتوقعها بسبب التقييم البطيء. على سبيل المثال:

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

سوف يؤدي إلى:

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

لأن @r يتم تقييمها بالفعل داخل a b (أي مكان استخدامها - وليس عند النقطة التي تحددها).
(لذلك أظن أن بعض حالات الاستخدام قد تتطلب في الواقع بناء لغة أخرى لهذا الغرض - وليس مجرد متغير. وقد تم اعتبار العديد من حالات الاستخدام الأخرى ذات الصلة من قبل كموضوع للرقم 1075).

في كثير من الحالات لن تعمل بالطريقة التي تتوقعها بسبب التقييم البطيء
أظن أن حالات استخدام معينة قد تتطلب في الواقع بناء لغة أخرى لهذا الغرض - وليس مجرد متغير

ستحتاج إلى بناء اللغة الخاص هذا لالتقاط سياق المحدد عند النقطة المحددة ، وليس عند النقطة التي يتم استدعاؤها من خلال تقييم المتغير الذي تم تعيينه له. يجب أن يصدر التقييم فقط السياق الذي تم التقاطه في موقع التعريف.

لا يختلف كثيرًا عن البحث عن المتغيرات عن طريق الإغلاق ، ولكن نعم ؛ سيتطلب بناء لغة خاص وليس وظيفة.

تضمين التغريدة

نعم ، أعتقد أننا كنا نناقش بعض الوظائف الزائفة selector في وقت سابق (زائف لأن تحليل الوظيفة العادية لا يمكنه التعامل مع كل تلك المجمعات المحددة المحددة على أي حال) ثم لأنها زائفة (أي نوع مخصص مثل Url ) لن يكون هناك مشكلة في جعله يسحب سياق تعريفه داخل (إذا كنت أتذكر بشكل صحيح DRs يفعلون مثل ذلك تمامًا).
لذا فإن شيئًا مثل <strong i="10">@foo</strong>: selector(&); يمكن أن يفعل خدعة على ما أعتقد. على الرغم من ظهور مشكلة ثانوية تالية:

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

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

لذلك قد يتطلب الأمر غير & عامل تشغيل / كلمة رئيسية. (أو ربما مجرد وظيفة زائفة مخصصة ، على سبيل المثال current-selector() ... حسنًا ، هذا يقودني الآن إلى فكرة ترميز نوع PseudoFunction لعدم تلويث واجهة برمجة التطبيقات لكل شيء صغير ، أوه! :).

أعلم أن هناك ترددًا عامًا في إضافة أشياء جديدة إلى اللغة ، ولكن محدد المحدد قد يكون مفيدًا. أحب | ، على الرغم من أنه جزء من بنية محدد CSS @namespace . ومع ذلك ، لا يبدو أن | مسموح له ببدء_ محدد ، لذلك لا ينبغي أن يتعارض. أنا أستخدمها لأنها تذكرني بـ "القيمة المطلقة" للرياضيات والتي تبدو مناسبة بشكل غامض ، و لأنها بسيطة. مجرد فكرة لإلهام المحادثة.

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

(في الواقع ، يمكن استخدامه لتعيين أن _any_ var يجب معالجتها وتخزينها على الفور ، أو أي شيء آخر؟ ولكن هذا يبدو وكأنه _way_ مفرط في النطاق.)

هل هو منتظم & أم saved-context-& ؟

انا اقول يجب القبض سياق محدد في موقع selector() يسمى الزائفة وظيفة و & ينبغي تقييمها ضمن _that_ السياق ويجب أن يتم تعيين النتيجة النهائية لهذا النوع الجديد من عقدة شجرة Selector .

عندما يتم إقحام أي متغير يحتوي على نوع Selector من عقدة الشجرة في محدد ، كما هو الحال مع استخدام @{var} في المثال ، يجب إنشاء المحدد الناتج بنفس الطريقة كما هو الحال عندما يكون المحرف & موجودًا في المحدد ، أي ؛ لا تنضم وتبدأ مع المحددات من مستوى متداخل واحد لأعلى.

السبب وراء ذلك هو أن كلاهما محددان تم التقاطهما: selector() هو أحد المحددات التي يلتقطها المستخدم ، بينما & هو المحدد "الأصل" الموجود دائمًا والذي تم التقاطه.

بعد ذلك ، إذا طلب المستخدم استيفاء عقدة Selector تم التقاطها مع سياق المحدد _current_ ، فيمكن أن يكون واضحًا بشأنه. على سبيل المثال & @{var} { ... }

في الختام

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

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

يجب أن تولد

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

بينما

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

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

يجب أن تولد

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

حسنًا ، @{var} مقابل & @{var} يبدو مصطنعًا تمامًا ، هذه ليست الطريقة التي تعمل بها هذه الأشياء في Less. ... { & div ... و ... { div ... عبارة عن بيانات متساوية دائمًا. أيضًا ، بدون احتساب هذا ، ماذا أفعل إذا كنت بحاجة إلى a b x, #y a b .z مع x, #y * .z معرّف في مكان آخر؟

أنا لست معجبًا ببنية تشبه الوظيفة للمحددات. أنا أؤيد القدرة على الإشارة إلى المحددات الموروثة أو تعديلها أو نقلها (التخصيص إلى المتغير وإعادة الاستخدام).

فقط للتأكد ، على الرغم من ذلك ، مقدار هذا الاختلاف في # 1075 (استهداف محددات الوالدين) أو في تعارض محتمل مع https://github.com/less/less-meta/issues/16#issuecomment -292679320 (تعيين محدد واحد لمتغير)؟ أم أن هذا يختلف عن مزيج الأسماء المستعارة لأن هذه

@ ماثيو دين
يتعلق الأمر بالفعل بالتقاط قائمة المحددات الفعلية ، وليس حول الحصول على مجموعة القواعد المقيمة ، وإخراج القائمة المذكورة لاستخدامها لاحقًا.

يمكن للمرء أن يتخيل وظيفة مثل extract(list,index) سيتم تحديثها لتكون قادرًا أيضًا على استخراج مكونات المحدد من قائمة المحددات والتعزيزات المماثلة لتسهيل العمل مع المحددات ، بحيث يمكن للمستخدمين التعامل معها بسهولة بطرق مثيرة للاهتمام. على سبيل المثال ، للمكونات التي تتبع أنظمة تسمية معينة مثل BEM.

على سبيل المثال أعطت mixin

.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;
    }
  }
}

التالية أقل

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

يولد CSS

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

لقد امتلك Sass ، afaik ، هذا لفترة طويلة وهناك العديد من الأمثلة على هذه التقنية التي يتم استخدامها بذكاء للغاية. في مصانع الكود كما في المثال الخاص بي ، أو لأغراض أخرى.

أما بالنسبة لل:

تعارض محتمل مع less / less-meta # 16 (تعليق) (تعيين محدد واحد إلى متغير)

أنا شخصياً أفترض السلوك التالي:
قيم محدد "تافهة" (على سبيل المثال ، .mixin ، .ns.mixin ، #foo .bar ، baz إلخ ، لحسن الحظ ، يغطي هذا أي شيء يمكن استخدامه / تعريفه على أنه mixin / function ) إلى متغير (أو يتم تمريرها كمعلمات لتعمل) مباشرة . أي أننا بالفعل لدينا هذا بالفعل:

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

^ هذا (بشكل أساسي) لا علاقة له بالمحددات على الإطلاق - هذه القيم (تمت محاولة تحويلها) إلى تنسيق محدد (للبحث عن مزيج) فقط عندما نحاول الاتصال بهم / تقييمهم باستخدام @var(...) أو @var[...]
(بشكل عام ، قد يكون الاصطلاح المنطقي هو نسيان أن معرفات mixin هي (يتم تمثيلها داخليًا على أنها) محددات ولكن دائمًا يجب التفكير فيها كمعرفات بنقطة فقط أو بادئة # ، وأشياء مثل .ns > .mixin to تتلاشى في النهاية باعتبارها زائدة عن الحاجة وغير مجدية :)

في حين أن المحددات المعقدة أو "الحقيقية" تتطلب selector وظيفة زائفة بسبب غموض بناء الجملة / المحلل اللغوي. أي أشياء مثل:

  • <strong i="29">@var</strong>:foo>bar <- محدد و (محتمل) تعبير منطقي
  • <strong i="32">@var</strong>:.1+.2; <- التعبير arithm و أقل صالحة محدد
    (إلخ. حسنًا ، تذكر فقط جميع رموز المحددات المحددة - يتعارض كل شيء تقريبًا مع شيء ما في سياق تحليل القيمة ، ويصبح هذا أكثر دراماتيكية عندما يُحتمل أن يتم تمرير القيم أعلاه إلى دالة / mixin كمعلمات في مكانها ، على سبيل المثال ، ما يلي مستحيل تمامًا لدعم w / o selector() :
    less: some-function(abc, selector(#foo .is :not(> bar)[baz="qux"], abc), selector(bla), 42); // ^ remove `selector()` and try to parse

أنا لست معجبًا ببنية تشبه الوظيفة للمحددات.

باختصار ، تعد الوظيفة الزائفة selector ضرورية فقط لاستبعاد أي تعارضات في بناء الجملة والدلالات الحالية والمحتملة مرة واحدة وإلى الأبد. لذلك أشك في أن لدينا بالفعل العديد من الخيارات هنا (يجب فقط فصل سياقات تحليل القيمة والمحدد بطريقة ما).


(كل ما سبق لا يعني أن القيمة التي يتم إرجاعها بواسطة selector() لا يمكن استخدامها ككيان قابل للاستدعاء ، على سبيل المثال @var() ، ربما - لكن هذا سيكون غير ضروري / عديم الفائدة ، لذلك بالكاد يستحق يزعج).

تضمين التغريدة

يمكن للمرء أن يتخيل وظيفة مثل extract(list,index) سيتم تحديثها لتكون قادرًا أيضًا على استخراج المحدد

بالتأكيد يمكننا ضبط الوظائف للعمل مع السلاسل بافتراض أن هذه السلسلة قد تحتوي على بعض المحددات ، لكن هذا يعني أن كل وظيفة من هذا القبيل (ليس فقط extract ) يجب تحديثها / تعديلها / تعديلها. سيكون النهج المعاكس أكثر كفاءة / أقل عبئًا. أي أنها إما وظيفة تحويل مخصصة selector-string->values ، أو حتى إعادة البنية المناسبة للعقد مباشرة بواسطة selector (في كلتا الحالتين ، الجزء الأكثر صعوبة هو كيفية حزم / فك حزم المجمعات المحددة مثل كل استخدام -حالة قد تفضل تمثيلًا مختلفًا).

(لاحظ أنه لا يزال يتعين على ميزة الاستيفاء المحدد في حد ذاتها تحويل @{var} إلى تنسيق مناسب في النهاية على أي حال ، لذلك لا يهم حقًا التنسيق الذي تأتي به قيمة هذا var - سواء كانت سلسلة أو مجهولة أو أيًا كان بنية العقد - يبقى معظم خداع التحويل كما هو).

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

لكي نكون صادقين ، يبدو هذا وكأنه تناسخ لـ "قرصنة JavaScript مضمنة و LessHat-like" ، لا يمكن منعه ولكن سيتم الإعلان عنه بقوة.
(بدون احتساب أن المثال مؤسف جدًا <- عد الأسطر) أفضل اقتراح بعض الشيء less-plugin-bem-selectors (حيث يمكنك ببساطة الحصول على وظيفة get-block-name ، راجع للشغل. & feature) بدلاً من هذه regexes القبيحة (أسلوب "استخدام معالج CSS المسبق كمعالج نص تعسفي" سوف يفقد في النهاية بشكل سيء في نهاية الأشياء المشابهة لـ PostCSS).

والعودة إلى & مقابل context-saving-& ، حتى الآن أخشى أنه ليس لدي أفكار أفضل من وضع علامة مخصصة للوظيفة ، على سبيل المثال selector(..., lazy or not) أو حتى اثنين وظائف منفصلة. أو باستخدام other-than-&-keyword (على سبيل المثال ، ). فقط لا ترى أي طريقة آمنة لحل غموض نقطة التقييم تلقائيًا.

أفضل اقتراح بعض الأشياء less-plugin-bem-selectors

قطعا. كان الاستخراج المستند إلى regex مجرد تقديم مثال لا يتضمن وظائف مخصصة. ؛)

أنا لست معجبًا ببنية تشبه الوظيفة للمحددات.

أيضًا ، إذا كنت تقصد فقط كيف يبدو ... يمكن أن يكون بعض الإنشاءات الأخرى بالطبع ، على سبيل المثال ⁞#foo:not(.bar)⁞ ، لكنك تعلم أننا نفدنا بالفعل الرموز المجانية. لذا لا يُقترح بناء جملة الدالة الزائفة إلا لأن لدينا بالفعل مثل هذا المفهوم مع url أي حال (وبالتالي لا داعي للتفكير في الأشياء التي يمكن لمفهوم جديد كسرها).

الآن ، الجزء الممتع.

لقد أنشأت تطبيقًا إضافيًا سريعًا وقذرًا لوظيفة current-selector (فقط لأرى كيف يمكن أن يكون منتفخًا ، أتوقع أنه بالطبع لا يمكن أن يكون مفيدًا للغاية بسبب التقييم الكسول var) ، وأعرف ماذا؟ هذا المثال الأساسي:

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

النتائج بـ r: div :)
لا توجد فكرة بالضبط عن أي جزء من كود المترجم يتعامل مع هذا السلوك المعين ، ولكن إليك مثال أكثر تقدمًا لتوضيح السحر:

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
    }
}

هناك فقط الكشوفات [2] و [3] يتم استدعاؤها مرتين (على سبيل المثال تم تقييمها كسول) ، بينما [1] ليست كذلك (على ما يبدو لأن القيمة لا تحتوي على أي متغيرات ، على الرغم من مرة أخرى ، لا أعرف ما إذا كان هذا مقصودًا أو مجرد تأثير جانبي لبعض التخزين المؤقت ، أو أنه قد يكون خطأ محظوظًا في الكود الخاص بي - على سبيل المثال ، قد يؤدي هذا السطر إلى مثل هذا التأثير الجانبي لهذا التخزين المؤقت - ولكن بعد ذلك ليس واضحًا لماذا تتأثر بالمتغيرات الإضافية - أي حاجة إلى مزيد من البحث).


أي أن إصدارًا يعتمد على المكون الإضافي لـ context-saving-& يبدو ممكنًا (باستثناء ذلك بالطبع بدلاً من <strong i="29">@var</strong>: & ستستخدم شيئًا مثل <strong i="31">@var</strong>: current-selector() ) على الرغم من أن الوظيفة لا ينبغي لديك أي معلمات وإلا فسيتم تقييمها كسولًا (إذا تم تمرير متغير) - وهذا أمر محزن لأنني خططت في البداية ليكون له أربعة :).
مسيء تمامًا ولكن يمكن أن يكون بمثابة حل بديل / متعدد التعبئة. مثال أكثر واقعية يعمل أيضًا حسب الرغبة:

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;
        }
    }
}

أي التخصيصات المتغيرة اللاحقة / استدعاءات الوظائف لا تؤثر على نقطة تقييم المتغير الأولي.

@ سبع مراحل كحد أقصى
أحبها.

حتى لو ألقى التقييم الكسول حاليًا مفتاح ربط في الأعمال عند وجود وسيطة معلمة ، فمن المفترض أن يكون هذا شيئًا يمكن حله من أجل تنفيذ "حقيقي".

أيضًا ، إذا كنت تقصد فقط كيف يبدو ... يمكن أن يكون بعض البناء الآخر بالطبع ، على سبيل المثال ⁞ # foo: ليس (.bar) ⁞ ، لكنك تعلم أننا نفدنا بالفعل الرموز المجانية.

عادل بما يكفي. لم أقم حقًا بلف عقلي حول هذا الأمر فيما يتعلق بالاستخدام وليس لدي أي أفكار أفضل. أعتقد أن هناك شيئًا مميزًا حول هذا الأمر ، لكن ربما لا. أعلم أنه كان هناك نقاش في وقت ما حول $() ، لكن انتهى بنا الأمر بتخصيص $ . راجع للشغل ، ألا يكون selectors() وليس selector() ؟ ألا يمكن أن تحتوي (مثل & ) على أي عدد من المحددات؟

ويبدو أن selector(&) أكثر منطقية من current-selector() . وهذا يعني: "إنشاء قائمة محددات من كائن X ، سواء كان ذلك & أو سلسلة". مهما كانت الصيغة النهائية تبدو وكأنها ستستغرق & كوسيطة.

ويبدو أن selector(&) أكثر منطقية من current-selector()

هذه أشياء مختلفة. current-selector هو مجرد متغير دالة لـ & (بما أن الأخير لا يدعمه المحلل اللغوي). بينما selector(...) هو ذلك التصحيح للمحلل اللغوي لدعم المحدد التعسفي (بما في ذلك & ).


أما بالنسبة لـ selectors - حسنًا ، إنه كذلك. ولكن نظرًا لأنها تمثل 99٪ من حالات استخدام المحدد الفردي ، أعتقد أن صيغة الجمع قد تبدو أقل وضوحًا بالنسبة لمعظم المستخدمين (في معظم الأحيان ، عادةً ما يطلقون على h1, h2, h3 {} كمحدد ويستمرون في الحديث عن مُحدِّد أقل من الوالدين (حتى إذا كان لإختيار الصورة) :) فلماذا يزعج؟

Ah ok.

@ ماثيو دين
صيغة الجمع والمفرد قابلة للتبديل إلى حد كبير لأي شخص باستثناء مؤلفي مواصفات CSS. إنفاكت ، افعل ذلك: لأي شخص بما في

بفرح شديد إن مصطلح الجمع "المحددات" ليس حتى الطريقة الرسمية لتعيين مجموعة مفصولة بفاصلة. إن المصطلحات الصحيحة تمامًا لصيغة الجمع هي ، في اعتقادي ، "قائمة المختارين".

لذا يمكنك أن ترى مدى عمق هذه الإشارة الغامضة في الحقيقة.

أعتقد أن المصطلحات الصحيحة لصيغة الجمع هي قائمة محددات.

نعم ، لقد بحثت أيضًا في w3c أمس ، إنها "مجموعة من المحددات" ، و "قائمة المحددات" وما إلى ذلك ، لا شيء يتوهم حقًا مثل غريب "المحدد هو سلسلة من تسلسل واحد أو أكثر من المحددات البسيطة المفصولة بمجمعات" هم أيضًا have there :) يتم استخدام نموذج "المحددات" فقط هناك لوصف شيء "أنواع المحددات".

"المحدِّد هو سلسلة من تسلسل واحد أو أكثر من المحددات البسيطة المفصولة بوحدات التجميع"

وبالنسبة لأي شخص يفكر في أنه قد يشير إلى قوائم مفصولة بفواصل: فهو ليس كذلك. يجب أن يكون الشكل الكامل لهذا الاقتباس: "المُحدِّد _complex_ عبارة عن سلسلة من تسلسل واحد أو أكثر من المحددات البسيطة المفصولة بمُجمِّعات."

تحتوي مواصفات CSS على مشكلة أخرى حيث يتم استخدام الشكل العام لـ "المحدد" في الغالب للإشارة إلى ما تسميه المواصفات رسميًا محددات معقدة. المحددات المعقدة عبارة عن محددات بسيطة ، على سبيل المثال tag ؛ #id ؛ .class ؛ [attr] ؛ وما إلى ذلك ، بالسلاسل عبر المجمِّعات ، على سبيل المثال > ؛ + ؛ ~ ، إلخ.

شيء مثل ul > li يسمى محددًا معقدًا.


تحذير ما يلي سيكون نوعًا من التشدق:

إن مواصفات CSS للأسف عبارة عن مستنقع من المصطلحات غير المتسقة وغير المعروفة. كلما عدت إلى الوراء ، ازداد الأمر سوءًا بشكل تدريجي. لا يساعد في استمرار الكثير من وحدات CSS3 في الرجوع إلى وحدات CSS 2.1 أو أن وحدات CSS3 الجديدة قد تم تحديدها عن طريق النسخ الحرفي لوثائق CSS 2.1 القديمة. المواصفات الخاصة بالمحددات ونموذج التنسيق المرئي هي الأسوأ على الرغم من ذلك ؛ الكثير من المصطلحات الغامضة ، التي تبدو متشابهة أو سيئة التسمية.

خذ على سبيل المثال شيئًا أقل أهمية بكثير من ul > li ، مثل [*|attr^="value" i] . هذا الأخير مصنف تقنيًا على أنه محدد بسيط. (نعم حقا.)

كان علي أن أحاول شرح أجزاء من مواصفات نموذج التنسيق المرئي الأخير لأحد زملائي الأكثر توجهاً نحو التصميم في وقت ما قبل بضع سنوات أيضًا. أعتقد أن بعض الصمامات قد انفجرت بالفعل في كل من أدمغتنا بينما كنا نمر عبر الممرات التي تعالج مفهوم مربعات الخطوط ولم يكن ذلك حتى أسوأ جزء منه. (حاول أن تخطو إلى la-la-land السحري وهو نموذج تنسيق الجدول ، إذا كان لديك القليل من القيمة لسلامتك العقلية.)

أفراح متنوعة لتوثيق المشاريع مفتوحة المصدر ...

خذ على سبيل المثال شيئًا أقل أهمية بكثير من ul > li ، مثل [*|attr^="value" i] . هذا الأخير مصنف تقنيًا على أنه محدد بسيط

هذا منطقي بالنسبة لي ، لول ، لمجرد أنه لا يستخدم المُدمج. يتبع التعريف بدقة. فقط لأنه يستخدم الكثير من الرموز لا يجعله أكثر "تعقيدًا". ul > li معقد لأنه يتضمن مجموعتين من الاستعلامات ، أي الاستعلام عن جميع العناصر المطابقة li ثم اجتياز الشجرة من كل منها لتحديد أي منها يحتوي على ul . هذا الأخير يختبر العناصر الفردية مرة واحدة فقط. إنه استعلام واحد لذلك فهو محدد بسيط.

إن مصطلح الجمع "المحددات" ليس حتى الطريقة الرسمية لتعيين مجموعة مفصولة بفاصلة. أعتقد أن المصطلحات الصحيحة لصيغة الجمع هي قائمة محددات.

صحيح ، أنت محق. "المحددات" هي في الحقيقة وحدات البت المحددة التي تسمح لك بتحديد العناصر ، ولكن ul > li > .title عبارة عن "محدد" مفرد. لذلك أعتقد أن selector() هو ، في الواقع ، ربما أقرب من الناحية المعنوية.

@ سبع مراحل كحد أقصى

ركضت للتو عبر مشكلة بسيطة أخرى تتعلق بوظيفة البرنامج المساعد السريع n-dirty: فهي لا تتعامل مع الوصول من ملف mixin ذي مساحة الاسم بشكل صحيح. Namespaces عبارة عن إطار عادي من النوع Ruleset ومن ثم يُضاف اسمها إلى المحددات.

من المحتمل أن يشمل التنفيذ الحقيقي هذه الحالة أيضًا.


[تعديل]
الحيلة لإنجاحها هي التحقق مما إذا كان أحد الإطارات في مكدس سياق الوظيفة هو MixinDefinition وإذا كان _is_ ، تخطى الإطارات التالية x على تلك المجموعة ، حيث x يساوي مقدار الإطارات في مكدس MixinDefinition .

(بشكل أساسي ؛ يتخطى هذا إطارات "الإغلاق" التي تمت إضافتها إلى المكدس عندما ينفذ MixinCall MixinDefinition .)

تمت إزالة التسمية "التي لا معنى لها". لا تزال هذه قضية جيدة للاستكشاف.

ربما current-selector() ليس سيئًا للغاية. على الرغم من أنه ، للتوضيح ، سيكون في الواقع current-selectors() . لكن هذا لا يزال مطولًا بعض الشيء. أعتقد أنني سأكون أكثر تفضيلًا إذا كان بإمكاننا التفكير في اسم وظيفة لـ "التقاط &" وهذا أكثر إيجازًا.

اسم وظيفة "الالتقاط &" وهذا أكثر إيجازًا.

ما عليك سوى تسميته &() . من الناحية المفاهيمية ، لا شيء أكثر من مجرد وسيلة للحصول على ما هو في & بعد كل شيء.
على سبيل المثال

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

🤔
أجل ، يجب أن يكون ذلك جيدًا. أي اعتراضات؟

سأحاول التلخيص لمعرفة ما إذا كنت أفهم الميزة المقترحة:

دالة جديدة تُرجع &() ما سينتجه & في السياق الحالي ، مما يسمح بذلك.

.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! */
    }
  }
}

وهذا كل ما سيخرج هذا.

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

لأن هذا مذهل ، وأنا أحبه.

بالتفكير في هذا الأمر أكثر ، أعتقد أن الأكثر إقناعًا بالنسبة لي (بعد التمريرة الأولى ؛ أوقفني إذا كنت أتصرف بجنون شديد) هو إمكانية وجود نمط "كتلة" (مجموعة قواعد) مكون موحد. بشكل أساسي ، أتمنى أنه بدلاً من حفظ قيمة سلسلة محدد بسيطة ، سيتم تعيين الوظيفة إلى _ " & ، ولكن في النطاق تم تعريف المتغير في" _ ، مما يسمح بنمط التأليف هذا لمكون (سأسمي هذا السلوك أ ):

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

ثم يمكنني القول "استخدم @this كل مكان بدلاً من & ".

سيكون قلقي الوحيد هو حالة الانقلاب (التي سأسميها السلوك ب ) ، لكن لا يمكنني التفكير في حالة مقنعة حيث أريد هذا السلوك. هذا هو أنني لا أستطيع أن أرى لماذا يريد شخص ما القيام بذلك.

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

لأن الطريقة الحالية لإنجاز ذلك _ بكثير_ أكثر إيجازًا (ويمكن قراءتها أيضًا ، بمجرد أن يكون & واضحًا في مفرداتك).

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

هل هناك حالة مقنعة (بصرف النظر عن صعوبة التنفيذ) للسلوك ب على السلوك أ؟

هذا مجرد واحد من تلك الأسئلة التي أعتقد أنه يجب الإجابة عليها قبل بدء العمل.


TL؛ DR: تصويتي هو لـ &() ليكون ديناميكيًا ، وهذا يعني بشكل أساسي _ " & ، ولكن كما لو كان متداخلًا هنا بدلاً من أعمق" _ ، بدلاً من إرجاع قيمة ثابتة _ " & الآن. "_

calvinjuarez الأمثلة الخاصة بك محيرة إلى حد ما لأنك لا تكتب مخرجاتك المتوقعة ، لذلك تبدو إلى حد ما في المجال النظري ، ولكن بشكل أساسي:

.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;
}

تعني بشكل أساسي "& ، ولكن كما لو كانت متداخلة هنا بدلاً من أعمق" ، بدلاً من إرجاع "قيمة & الآن" ثابتة.

أنا حقًا لا أفهم ما يعنيه هذا.

طريقة أخرى للتفكير في هذا. هذه:

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

هو معادل للكتابة:

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

@ ماثيو دين

نعم. لكن فكر في الأمر من خلال عدسة mixins ، حيث سيحصل &() على سياق محدد المتصل mixin.

إنه يمكّن من كتابة مكونات قائمة على mixin حيث يمكن للمؤلفين أنفسهم أن يقرروا بحرية جذر اسم الفئة بطريقة طبيعية. على سبيل المثال

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

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

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

يمكن للمزيجات المستخدمة هناك قراءة الفصل عبر &() وتشغيلها في مخرجاتها بشكل مناسب. على سبيل المثال ، يمكن أن يحتوي المحدد الذي تم التقاطه للقواعد الثانية والثالثة على تحلل بنية BEM للحصول على فئة الكتلة الأساسية ، والتي يمكن استخدامها لإنشاء تجاوزات لمحددات العناصر المتداخلة.

هذا هو؛ يمكن استخدامه لإنشاء محدد مثل .my-button--wide > .my-button__text ، دون الحاجة إلى تمرير أي أسماء محددات كمعلمات. فقط من سياق محدد المستدعي وحده.


تتجنب المصانع المكونة القائمة على Mixin مثل هذا العديد من مشاكل طريقنا أو الطريق السريع التي تواجهنا باستخدام أطر التصميم "الكل أو لا شيء". إنها تسمح لك بتسجيل إطار العمل ، ولكن اختر بدقة المكونات التي تريد دمجها بالفعل وتحت أي اسم.

تضمين التغريدة

يمكن للمزيجات المستخدمة هناك قراءة الفصل عبر & () والعمل به في مخرجاتهم بشكل مناسب. على سبيل المثال ، يمكن أن يحتوي المحدد الذي تم التقاطه للقواعد الثانية والثالثة على تحلل بنية BEM للحصول على فئة الكتلة الأساسية ، والتي يمكن استخدامها لإنشاء تجاوزات لمحددات العناصر المتداخلة.

نعم ، فهمت. من المحتمل أن يكون أكثر فائدة في الخلطات. أنا بالتأكيد أحصل على فائدة &() أكثر من استخدام اسم المحدد المباشر. كانت وجهة نظري هي محاولة توضيح قيمة &() في المثال المحدد.

للمضي قدمًا ، أعتقد أنه حل نحوي جيد ، وسأعطي شخصيًا 👍 للمضي قدمًا في تنفيذ &() ، إذا أراد شخص ما توليه.

@ ماثيو دين

الأمثلة الخاصة بك محيرة إلى حد ما لأنك لا تكتب مخرجاتك المتوقعة

عذرًا ، معذرة. سأعيد صياغتها بشكل صحيح. أشعر أن &() ستكون ميزة أقوى إذا تم تجميع أقل هنا في CSS أدناه.

.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 */
}

إذا كان <strong i="15">@this</strong>:&(); يتصرف تمامًا مثل <strong i="17">@this</strong>:.component; في هذه الحالة ، فإننا نحيل هذه الميزة إلى الأداة المساعدة _ only_ داخل mixins ، لكنني أعتقد أن لديها المزيد لتقدمه.

تعني بشكل أساسي "& ، ولكن كما لو كانت متداخلة هنا بدلاً من أعمق" ، بدلاً من إرجاع "قيمة & الآن" ثابتة.

أنا حقًا لا أفهم ما يعنيه هذا.

هذا يعني أنني أعتقد أن .thing{ & {} } و .thing{ <strong i="11">@amp</strong>:&(); @{amp} {} } يجب أن ينتجا نفس الناتج.

هذا يعني ، من الناحية العملية ، أنك لست مضطرًا لكتابة mixin لعمل BEM السهل ، ولكن يمكنك تحديده بشكل مضمّن. العودة إلى أحد الأمثلة القديمة:

_component.less_

.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! */
    }
  }
}

↓↓↓

_component.css_

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

الميزة: ليس عليك أن تسأل فريقك عما إذا كانوا يقصدون & أو @{this} . ما عليك سوى قول "استخدم فقط @{this} كل مكان."

سيؤدي في الواقع إلى جعل تعريف مزيج المصنع المكون أكثر اتساقًا داخليًا أيضًا.

_hypothetical-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;
      }
    }
  }
}
// ...

_hypothetical-styles.less_

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

_hypothetical-styles.css_

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

وهذا يعني أنني أعتقد أن .thing {& {}} و .thing { amp : & ()؛ @ {amp} {}} يجب أن ينتج نفس الناتج.

نعم ، أعتقد أننا نقول نفس الأشياء ولكن دعني أؤكد بهذا المثال. هذه هي الطريقة التي أرى بها هذه الميزة مقابل & في نفس المكان.

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

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

بينما:

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

سينتج:

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

calvinjuarez أعتقد أنني كنت في حيرة من مثالك . &() أساسي مثل this.selectors.toCSS() Eval'd في هذا الموقع ( ليس حقًا ، ولكن للتوضيح فقط ... في الواقع قد يكون هذا هو أسرع طريقة للقيام بذلك). ثم إدخال هذه السلسلة في أماكن أخرى لإعادة تقييمها كمحددات.

@ ماثيو دين
سيكون من الرائع في الواقع أن يعرض قائمة المحددات كقائمة فعلية للمحددات ، بما في ذلك السلوك الخاص لتوسيع المحددات بناءً على جميع أعضاء القائمة.

لديك على سبيل المثال

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

  @{this} {
    c : d;  
  }
}

انتاج

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

تمامًا مثل & الأصلي.

نعم ، هذا بالضبط ما ستفعله. في الإصدار 3.5 ، تؤدي أي متغيرات يتم تقييمها في المحددات إلى إعادة تحليل قائمة المحددات بالكامل كقائمة محددات جديدة. لذا نعم ، هذا سيعمل كما هو متوقع. إنه في الواقع سهل للغاية بسبب بعض العلاقات العامة الأخيرة التي قمت بها.

في 7 تموز (يوليو) 2018 ، الساعة 10:34 صباحًا ، كتب rjgotten [email protected] :

@ ماثيو دين
سيكون الأمر أكثر روعة في الواقع إذا كان سيعرض قائمة المحدد كقائمة فعلية من المحددات ، بما في ذلك السلوك الخاص لتوسيع المحددات استنادًا إلى جميع أعضاء القائمة.

لديك على سبيل المثال

.a و .b {
@ هذا : & () ؛

@{هذه} {
ج: د ؛
}
}
انتاج

.a .a ،
.a .b،
.ب. .أ،
.a .b {
ج: د
}
تماما مثل السكان الأصليين وسوف.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو اعرضها على GitHub ، أو قم بكتم صوت الموضوع.

.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;
}

.component الإضافي هو ما أعارضه. أقترح أنه يجب أن يعمل مثل هذا:

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; }

على الرغم من ذلك ، يبدو أن الميزة تسير في اتجاه مختلف. أردت فقط توضيح موقفي.

أقترح أنه يجب أن يعمل مثل هذا:

على سبيل المثال ، إذا كان هناك رمز استبدال في محدد يمثل قائمة _selector_ بدلاً من _string_ عاديًا ، فعندئذٍ يعمل رمز الاستبدال كما لو تم تحديد & و _ تعطيل_ تسلسل المحدد الطبيعي الذي ينتج عن التداخل.

إذا كان على &() إخراج نوع عقدة يجعله قابلاً للتحديد كقائمة محددات فعلية ، فسيكون هذا السلوك سهل التحقيق نسبيًا ، على ما أعتقد.

إنفاكت ، إذا كان لإخراج نوع عقدة مخصص ، فقد يساعد ذلك أيضًا في إنشاء وظائف البرنامج المساعد من أجل معالجة قائمة المحددات الملتقطة لاحقًا.

بالنسبة لي ، هذا يبدو وكأنه جعل & () يقوم بالكثير من العمل في وقت واحد. إذا كنت ترغب في حفظ المحددات في متغير ، فهذا شيء واحد ، ولكن جعل تسلسل المحدد تعطيل المتغير بسبب _content_ سيكون غير واضح في بناء الجملة. يمكن أن يأتي هذا المتغير من أي مكان (على سبيل المثال تم تمريره من mixin) ويمكن إنشاء قائمة المحدد بواسطة تخصيص متغير بسيط. أي أنه ليس من الواضح من الاستخدام المتغير أن سلوك تسلسلي مختلف سيحدث بناءً على محتويات المتغير.

أعتقد أنك إذا أردت تعطيل التسلسل ، فسيتعين عليك تحديد رغبتك في استبدال القيمة الضمنية وقيمة أخرى ، مثل (سامح التنسيق ، أنا على هاتفي) -

.مكون {
@ فار : & () ؛
& (@ var) _child {} // أو "استبدال &" بناء الجملة
}

لذا فهمت سبب كون النتيجة مرغوبة ، لكن IMO لا يمكننا فقط "التبديل السحري" لسلوك دمج متغير بناءً على المكان الذي تأتي منه قائمة المحددات. هذا يتطلب ميزتين مختلفتين.

أوه ... أنا في الواقع أحب الشيء &(...) ...

ها حقا؟ لا تعتقد أنه سيكون هناك ارتباك دلالي بين &() (محددات الالتقاط من &) و &(@arg) (استبدال و مع المحددات)؟

قد ترغب في عدم مزجها ، حيث قد يرغب شخص ما في استبدال & بمحدد فارغ من أجل التخلص منه بشكل أساسي. (لوضع الطفل في الجذر.) على الرغم من أنني أعتقد أنه قد يكون &(“”) طفل؟

لا أعلم ، إنه يستحق بعض التفكير / الاعتبار.

أيضًا ، كما هو مذكور في مؤشر ترابط "المحددات الرئيسية يجب أن يكون لها أهداف" ، هناك حالات استخدام لاستبدال أجزاء معينة من المحدد الموروث (أو كليًا) ، لذا عند التفكير في ذلك ، أعتقد أنه يجب تتبعها كمسألتين منفصلتين. يجب أن تتعلق هذه المشكلة فقط بالتقاط الصور

فقط لإغلاق هذه الدائرة ، هنا حيث ذكرت تغيير & في المكان باستخدام بنية تشبه الوظيفة. - https://github.com/less/less.js/issues/1075#issuecomment -397697714

لذلك ، أفضل ما إذا كان النقاش حول "كيفية / ما إذا كان سيتم تغيير الميراث & " يظل في سلسلة المحددات الرئيسية ، وهذا الموضوع يدور حول ما إذا كان <strong i="9">@var</strong>: &() مناسبًا أم لا لالتقاط in -place & selector في متغير. والذي ، في رأيي ، لا يزال يبدو جيدًا ، على الرغم من الخيط الآخر. لست متأكدًا مما إذا كانت هناك فرصة للقيام بالأمرين أم لا.

أحاول أن أفعل هذا

.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+_: @&;
    }
}

لكن هذا لن ينجح حتى يتم تنفيذ ذلك

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات