Less.js: Menyimpan pemilih ke variabel

Dibuat pada 20 Apr 2017  ·  50Komentar  ·  Sumber: less/less.js

Kami memiliki solusi ini:

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

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

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

Saya mengusulkan untuk menambahkan fitur: menulis <strong i="9">@r</strong>: &; alih-alih <strong i="11">@r</strong>: ~".selector"; untuk mendapatkan pemilih saat ini dan menyimpannya dalam variabel apa pun.

Contoh:

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

Semua 50 komentar

Anehnya saya benar-benar yakin permintaan seperti itu sudah ada. Rupanya tidak.
(Meskipun jelas ide itu muncul di banyak tiket sebelumnya: #1174, https://github.com/less/less.js/issues/1075#issuecomment-16891103 dll.)
Jadi biarlah kurasa.


Btw., untuk berjaga-jaga (dan untuk mengumpulkan beberapa kasus penggunaan untuk memikirkan kemungkinan konflik impl./sintaks):
Bagaimana Anda akan menggunakannya? Saya menduga dalam banyak kasus itu tidak akan berfungsi seperti yang Anda harapkan karena evaluasi yang malas. Misalnya:

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

akan menghasilkan:

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

Karena nilai @r benar-benar dievaluasi di dalam a b (yaitu di mana ia digunakan - bukan pada titik Anda mendefinisikannya).
(Jadi saya menduga kasus penggunaan tertentu mungkin sebenarnya memerlukan beberapa konstruksi bahasa lain untuk ini - bukan hanya variabel. Dan banyak kasus penggunaan terkait lainnya yang dipertimbangkan sebelumnya sebagai subjek #1075).

dalam banyak kasus itu tidak akan bekerja seperti yang Anda harapkan karena evaluasi yang malas
Saya menduga kasus penggunaan tertentu mungkin benar-benar memerlukan beberapa konstruksi bahasa lain untuk ini - bukan hanya variabel

Anda memerlukan konstruksi bahasa khusus untuk menangkap konteks pemilih pada titik yang ditentukan, bukan pada titik yang dipanggil dengan evaluasi variabel yang ditugaskan. Evaluasi seharusnya hanya memancarkan konteks yang ditangkap di situs definisi.

Tidak jauh berbeda dengan mencari variabel berdasarkan penutupan, tapi ya; itu akan membutuhkan konstruksi bahasa khusus dan bukan fungsi.

@rjgotten

Ya, saya kira kita telah membahas beberapa fungsi semu selector sebelumnya (semu karena penguraian fungsi biasa tidak dapat menangani semua kombinator khusus pemilih itu) dan kemudian karena itu semu (yaitu tipe khusus seperti Url ) tidak akan menjadi masalah untuk membuatnya menarik konteks definisinya di dalam (jika saya ingat dengan benar, DR melakukan persis seperti itu).
Jadi sesuatu seperti <strong i="10">@foo</strong>: selector(&); saya kira bisa melakukan trik. Meskipun kemudian masalah kecil berikutnya muncul:

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

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

Jadi mungkin memerlukan selain & operator/kata kunci. (Atau mungkin hanya fungsi semu khusus, misalnya current-selector() ... Hmm, sekarang saya mendapat ide untuk mengkodekan tipe PseudoFunction generik agar tidak mencemari API setiap barang kecil, owh! :).

Saya tahu ada keraguan umum untuk menambahkan hal-hal baru ke bahasa, tetapi penentu pemilih bisa berguna. Saya suka | , meskipun ini adalah bagian dari sintaks pemilih CSS @namespace . Namun, sepertinya | tidak diizinkan untuk _memulai_ pemilih, jadi seharusnya tidak bertentangan. Saya menggunakannya karena itu mengingatkan saya pada "nilai absolut" Math yang tampaknya agak sesuai, dan karena itu sederhana. Hanya sebuah pemikiran untuk menginspirasi percakapan.

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

(Faktanya, ini dapat digunakan untuk menunjukkan bahwa _any_ var harus segera diproses dan disimpan, atau apa pun? Tapi itu terasa seperti _way_ over-scoping.)

apakah itu biasa & atau saved-context-& ?

Saya akan mengatakan konteks pemilih harus ditangkap di situs fungsi semu selector() dipanggil dan & harus dievaluasi dalam konteks _that_ dan hasil akhir harus ditetapkan ke tipe baru ini dari Selector simpul pohon.

Ketika variabel _any_ memegang Selector jenis simpul pohon diinterpolasi ke dalam pemilih, seperti halnya penggunaan @{var} dalam contoh, pemilih yang dihasilkan harus dibangun dengan cara yang sama seperti ketika interpolator & hadir di pemilih, yaitu ; jangan bergabung dan awali dengan pemilih dari satu tingkat ke atas.

Alasan di balik ini adalah bahwa keduanya adalah pemilih yang ditangkap: selector() adalah yang diambil oleh pengguna, sedangkan & adalah pemilih 'induk' yang selalu ada dan ditangkap.

Kemudian, jika pengguna memerlukan interpolasi dari simpul Selector ditangkap bersama dengan konteks pemilih _current_, mereka dapat secara eksplisit menjelaskannya. Misal & @{var} { ... }

Sebagai penutup

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

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

harus menghasilkan

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

Sedangkan

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

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

harus menghasilkan

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

Hmm, @{var} vs. & @{var} terlihat sangat artifisial, ini bukan cara kerjanya di Less. ... { & div ... dan ... { div ... selalu merupakan pernyataan yang sama. Juga, bahkan tidak menghitung ini, apa yang harus saya lakukan jika saya membutuhkan a b x, #y a b .z dengan x, #y * .z didefinisikan di tempat lain?

Saya bukan penggemar konstruksi seperti fungsi untuk penyeleksi. Saya mendukung untuk dapat mereferensikan, memodifikasi, atau mengangkut (menetapkan ke variabel dan menggunakan kembali) penyeleksi yang diwarisi.

Hanya untuk memastikan, seberapa banyak variasi ini pada #1075 (menargetkan pemilih induk) atau dalam kemungkinan konflik dengan https://github.com/less/less-meta/issues/16#issuecomment -292679320 (menetapkan pemilih tunggal ke variabel)? Atau apakah ini berbeda dengan mixin aliasing karena ini adalah daftar pemilih dan bukan pemilih yang dievaluasi (atau mixin), dan outputnya adalah daftar pemilih dan bukan kumpulan aturan yang dievaluasi? Saya berasumsi fitur ini berbeda; Saya hanya ingin memastikan bahwa semua ini bergerak ke arah yang sama.

@matthew-dean
Ini memang tentang menangkap daftar pemilih yang sebenarnya, bukan tentang menangkap kumpulan aturan yang dievaluasi, dan mengeluarkan daftar tersebut untuk digunakan lebih lanjut.

Orang dapat membayangkan fungsi seperti extract(list,index) diperbarui agar dapat juga mengekstrak komponen pemilih dari daftar pemilih dan peningkatan serupa untuk memudahkan bekerja dengan pemilih, sehingga pengguna dapat dengan mudah memanipulasinya dengan cara yang menarik. Misalnya untuk komponen yang mengikuti skema penamaan tertentu seperti BEM.

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

berikut Kurang

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

menghasilkan CSS

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

Sass telah, afaik, memiliki ini untuk waktu yang lama dan ada banyak contoh teknik ini yang digunakan dengan sangat cerdas. Di pabrik kode seperti pada contoh saya, atau untuk tujuan lain.

Adapun:

kemungkinan konflik dengan less/less-meta#16 (komentar) (menetapkan pemilih tunggal ke variabel)

Secara pribadi saya menganggap perilaku berikut:
Nilai pemilih "Sepele" (misalnya .mixin , .ns.mixin , #foo .bar , baz dll, untungnya ini mencakup apa pun yang dapat digunakan/didefinisikan sebagai mixin/fungsi ) ditugaskan ke variabel (atau diteruskan sebagai parameter ke fungsi) secara langsung . Yaitu kita sebenarnya sudah memiliki ini:

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

^Ini (pada dasarnya) tidak ada hubungannya dengan penyeleksi sama sekali - nilai ini (diusahakan untuk) dikonversi ke format pemilih (untuk mencari mixin) hanya ketika kami mencoba memanggil/mengevaluasinya dengan @var(...) atau @var[...] pernyataan
(Secara umum, konvensi logis adalah melupakan bahwa pengidentifikasi mixin adalah (diwakili secara internal sebagai) penyeleksi tetapi selalu menganggapnya sebagai pengidentifikasi hanya dengan awalan titik atau # , dan hal-hal seperti .ns > .mixin untuk memudar akhirnya sebagai berlebihan dan tidak berguna :)

Sedangkan pemilih yang kompleks atau "nyata" memerlukan fungsi semu selector karena ambiguitas sintaks/parser. Yaitu hal-hal seperti:

  • <strong i="29">@var</strong>:foo>bar <- pemilih dan (berpotensi) ekspresi logis
  • <strong i="32">@var</strong>:.1+.2; <- ekspresi aritma dan pemilih yang valid Lebih sedikit
    (dll. ingat saja semua simbol pemilih tertentu - hampir setiap konflik dengan sesuatu dalam konteks penguraian nilai, dan ini menjadi lebih dramatis ketika nilai di atas berpotensi diteruskan ke fungsi/mixin sebagai parameter di tempat, misalnya berikut ini tidak mungkin untuk mendukung tanpa selector() :
    less: some-function(abc, selector(#foo .is :not(> bar)[baz="qux"], abc), selector(bla), 42); // ^ remove `selector()` and try to parse

Saya bukan penggemar konstruksi seperti fungsi untuk penyeleksi.

Singkatnya, fungsi semu selector hanya diperlukan untuk memotong sintaks dan konflik semantik saat ini dan potensial sekali dan selamanya. Jadi saya ragu kita benar-benar memiliki terlalu banyak opsi di sini (konteks penguraian nilai dan pemilih harus dipisahkan entah bagaimana).


(Semua di atas tidak berarti bahwa nilai yang dikembalikan oleh selector() tidak dapat digunakan sebagai entitas yang dapat dipanggil misalnya @var() , mungkin saja - tetapi itu hanya tidak perlu/tidak berguna, jadi hampir tidak layak untuk mengganggu).

@rjgotten

Orang bisa membayangkan fungsi seperti extract(list,index) diperbarui untuk dapat juga mengekstrak pemilih

Tentu kita dapat menyesuaikan fungsi untuk bekerja dengan string dengan asumsi string tersebut mungkin berisi beberapa pemilih, tetapi itu berarti setiap fungsi tersebut (bukan hanya extract ) harus diperbarui/disesuaikan/dimodifikasi. Pendekatan sebaliknya akan lebih efisien / kurang membebani. Yaitu itu adalah fungsi konversi selector-string->values , ATAU bahkan mengembalikan struktur simpul yang tepat secara langsung oleh selector (dalam kedua kasus, bagian yang paling rumit adalah cara mengemas/membongkar kombinator pemilih setiap kali digunakan -case mungkin lebih suka representasi yang berbeda).

(Perhatikan bahwa fitur interpolasi pemilih itu sendiri masih harus mengonversi @{var} ke format yang tepat pada akhirnya sehingga tidak masalah format apa nilai var itu masuk - apakah itu string, anonim atau apa pun struktur node - sebagian besar tipu daya konversi tetap sama).

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

Sejujurnya, ini terlihat seperti reinkarnasi dari "JavaScript sebaris dan peretasan seperti LessHat", tidak dapat dilarang tetapi akan diiklankan secara agresif.
(Tidak termasuk bahwa contohnya sangat disayangkan <- hitung barisnya) Saya lebih suka menyarankan beberapa hal less-plugin-bem-selectors (di mana Anda dapat memiliki fungsi get-block-name , btw. & fitur) alih-alih regex jelek seperti itu (pendekatan "Menggunakan praprosesor CSS sebagai prosesor teks arbitrer" pada akhirnya akan sangat longgar pada akhirnya untuk hal-hal seperti PostCSS).

Dan kembali ke & vs. context-saving-& , sejauh ini saya khawatir saya tidak memiliki ide yang lebih baik daripada flag khusus untuk fungsi tersebut, misalnya selector(..., lazy or not) , atau bahkan dua fungsi yang terpisah. Atau menggunakan other-than-&-keyword (misalnya ). Tidak dapat melihat metode aman apa pun untuk secara otomatis menyelesaikan ambiguitas titik evaluasi.

Saya lebih suka menyarankan beberapa hal less-plugin-bem-selectors

Sangat. Ekstraksi berbasis regex hanya untuk memberikan contoh yang tidak melibatkan fungsi kustom. ;)

Saya bukan penggemar konstruksi seperti fungsi untuk penyeleksi.

Juga, jika yang Anda maksud hanyalah tampilannya ... Tentu saja itu bisa berupa konstruksi lain, misalnya ⁞#foo:not(.bar)⁞ , tetapi Anda tahu kami sudah kehabisan simbol gratis. Jadi sintaks fungsi semu hanya disarankan karena kita sudah memiliki konsep seperti itu dengan url (jadi tidak perlu memikirkan hal-hal yang bisa atau akan dihancurkan oleh konsep baru).

Sekarang, bagian yang menyenangkan.

Saya membuat implementasi plugin yang cepat dan kotor dari fungsi current-selector (hanya untuk melihat seberapa besar kemungkinannya, berharap bahwa tentu saja itu tidak bisa sangat berguna karena evaluasi malas var), dan tahu apa? Contoh dasar ini:

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

menghasilkan r: div :)
Tidak tahu persis bagian mana dari kode kompiler yang menangani perilaku khusus ini, tetapi berikut adalah contoh yang lebih maju untuk menggambarkan keajaiban:

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

Hanya ada pernyataan [2] dan [3] yang dipanggil dua kali (yaitu sebenarnya malas-dievaluasi), sedangkan [1] tidak (tampaknya karena nilainya tidak mengandung variabel apa pun, meskipun sekali lagi saya tidak tahu apakah ini disengaja atau hanya efek samping dari beberapa caching, atau itu bisa menjadi bug keberuntungan dalam kode saya - misalnya baris ini dapat memicu efek samping seperti itu untuk caching ini - tetapi kemudian tidak jelas mengapa itu dipengaruhi oleh variabel tambahan - yaitu diperlukan lebih banyak penelitian).


Artinya, versi context-saving-& berbasis plugin tampaknya mungkin (kecuali tentu saja alih-alih <strong i="29">@var</strong>: & Anda akan menggunakan sesuatu seperti <strong i="31">@var</strong>: current-selector() ) Meskipun fungsinya tidak memiliki parameter apa pun jika tidak maka akan dievaluasi dengan malas (jika variabel dilewatkan) - ini menyedihkan karena saya awalnya merencanakannya untuk memiliki empat :).
Cukup kasar tetapi bisa berfungsi sebagai solusi/polyfill. Contoh yang lebih nyata juga berfungsi seperti yang diinginkan:

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

yaitu penetapan variabel / pemanggilan fungsi berikutnya tidak mempengaruhi titik evaluasi dari variabel awal.

@seven-fase-max
Suka sekali.

Bahkan jika lazy-evaluation saat ini sedang bekerja ketika argumen parameter hadir, _that_ mungkin adalah sesuatu yang dapat diselesaikan untuk implementasi 'nyata'.

Juga, jika yang Anda maksud hanyalah tampilannya... Tentu saja itu bisa berupa konstruksi lain, misalnya # foo:not (.bar)⁞, tetapi Anda tahu kami sudah kehabisan simbol gratis.

Cukup adil. Saya belum benar-benar membungkus otak saya tentang hal ini sejauh penggunaan saya juga tidak punya ide yang lebih baik. Saya kira sepertinya ada sesuatu yang istimewa tentang ini, tapi mungkin tidak. Saya tahu ada diskusi di beberapa titik tentang $() , tetapi kami akhirnya mengambil $ . Btw, bukannya selectors() dan bukan selector() ? Tidak bisakah (seperti & ) berisi sejumlah pemilih?

Dan sepertinya selector(&) lebih masuk akal daripada current-selector() . Yaitu: "buat daftar pemilih dari objek X, baik itu & atau string". Apa pun sintaks finalnya, sepertinya dibutuhkan & sebagai argumen.

Dan sepertinya selector(&) lebih masuk akal daripada current-selector()

Ini adalah hal yang berbeda. current-selector hanyalah varian fungsi dari & (karena yang terakhir tidak didukung oleh parser). Sementara selector(...) adalah patch untuk parser untuk mendukung pemilih arbitrer (termasuk & ).


Adapun selectors - baik, itu. Tetapi karena ini 99% dari kasus penggunaan pemilih tunggal, saya kira bentuk jamak akan terdengar kurang jelas bagi sebagian besar pengguna (di sebagian besar, mereka biasanya menyebut h1, h2, h3 {} sebagai pemilih dan terus berbicara tentang Selektor induk yang lebih sedikit (bahkan jika pemilih s ) :) Jadi mengapa repot-repot?

baiklah.

@matthew-dean
Bentuk jamak dan tunggal cukup banyak dapat dipertukarkan untuk siapa saja kecuali penulis spesifikasi CSS. Faktanya, buat itu: untuk siapa saja termasuk penulis spesifikasi, karena bahkan spesifikasi CSS sendiri menjadi mangsa penggunaan bentuk tunggal dan jamak secara bergantian.

Cukup meriah; istilah jamak 'pemilih' bahkan bukan cara resmi untuk menunjuk himpunan yang dipisahkan koma. Terminologi yang benar-benar tepat untuk bentuk jamak, menurut saya, adalah _selector list_.

Jadi Anda bisa melihat seberapa dalam sebenarnya referensi ambigu ini berakar.

Terminologi yang benar-benar tepat untuk bentuk jamak adalah, saya percaya, daftar pemilih.

Ya, saya juga melakukan pencarian w3c kemarin, itu "grup penyeleksi", "daftar pemilih", dll., Tidak ada yang benar-benar mewah seperti yang aneh "Pemilih adalah rantai dari satu atau lebih urutan penyeleksi sederhana yang dipisahkan oleh kombinator" mereka juga have there :) Hanya formulir "pemilih" yang sebagian besar digunakan di sana untuk menggambarkan hal "tipe pemilih".

"Pemilih adalah rantai dari satu atau lebih urutan selektor sederhana yang dipisahkan oleh kombinator"

Dan bagi siapa pun yang berpikir itu mungkin merujuk ke daftar yang dipisahkan koma: tidak. Bentuk lengkap dari kutipan tersebut seharusnya: "pemilih _kompleks_ adalah rantai dari satu atau lebih urutan penyeleksi sederhana yang dipisahkan oleh kombinator."

Spesifikasi CSS memiliki masalah lain di mana bentuk umum "pemilih" digunakan sebagian besar untuk merujuk pada apa yang secara resmi disebut oleh spesifikasi _penyeleksi kompleks_. Selektor kompleks adalah selektor sederhana, misalnya tag ; #id ; .class ; [attr] ; dll. , dirantai melalui kombinator, misalnya > ; + ; ~ , dll.

Sesuatu seperti ul > li disebut pemilih kompleks.


PERINGATAN berikut akan menjadi sedikit kata-kata kasar:

Sayangnya, spesifikasi CSS adalah lumpur dari terminologi yang tidak konsisten dan tidak tepat. Semakin jauh Anda mundur, semakin buruk keadaannya. Tidak membantu bahwa banyak modul CSS3 terus merujuk kembali ke modul CSS 2.1 atau bahwa modul CSS3 baru ditentukan dengan menyalin dokumentasi CSS 2.1 lama mereka kata demi kata. Namun, spesifikasi untuk penyeleksi dan model pemformatan visual adalah pelanggar terburuk; begitu banyak istilah yang ambigu, terdengar mirip, atau tidak jelas namanya.

Ambil contoh sesuatu yang jauh lebih sepele daripada ul > li , seperti [*|attr^="value" i] . Yang terakhir ini secara teknis diklasifikasikan sebagai pemilih sederhana. (Ya, sungguh.)

Saya harus mencoba dan menjelaskan bagian dari spesifikasi model pemformatan visual yang terakhir kepada salah satu rekan saya yang lebih berorientasi desain pada satu titik beberapa tahun yang lalu juga. Saya pikir beberapa sekering benar-benar putus di _keduanya_ otak kita saat kita membahas bagian-bagian yang membahas konsep kotak garis dan itu bahkan bukan bagian terburuknya. (Cobalah melangkah ke la-la-land ajaib yang merupakan model pemformatan tabel, jika Anda memiliki sedikit nilai untuk kewarasan Anda.)

Bermacam-macam kesenangan dari dokumentasi proyek sumber terbuka...

Ambil contoh sesuatu yang jauh lebih sepele daripada ul > li , seperti [*|attr^="value" i] . Yang terakhir ini secara teknis diklasifikasikan sebagai pemilih sederhana

Itu sebenarnya masuk akal bagi saya, lol, hanya karena tidak menggunakan kombinator. Ini mengikuti definisi dengan tepat. Hanya karena menggunakan banyak simbol tidak membuatnya lebih "kompleks". ul > li rumit karena melibatkan dua set kueri yaitu kueri untuk semua elemen yang cocok li dan kemudian melintasi pohon dari masing-masing untuk menentukan mana yang berisi ul . Yang terakhir hanya menguji elemen individu sekali. Ini satu kueri jadi ini adalah pemilih sederhana.

istilah jamak 'pemilih' bahkan bukan cara resmi untuk menunjuk himpunan yang dipisahkan koma. Terminologi yang benar-benar tepat untuk bentuk jamak adalah, saya percaya, daftar pemilih.

Benar, Anda benar. "Pemilih" sebenarnya hanyalah bit yang ditentukan yang memungkinkan Anda untuk memilih elemen, tetapi ul > li > .title adalah "pemilih" tunggal. Jadi saya kira selector() sebenarnya mungkin lebih dekat secara semantik.

@seven-fase-max

Baru saja mengalami masalah kecil lainnya dengan fungsi plugin quick-n-dirty: tidak menangani akses dari mixin namespace dengan benar. Ruang nama adalah bingkai tipe Ruleset dan dengan demikian namanya ditambahkan ke dalam pemilih.

Implementasi nyata mungkin harus mencakup kasus itu juga.


[EDIT]
Trik untuk membuatnya berfungsi adalah dengan memeriksa apakah salah satu bingkai pada tumpukan konteks fungsi adalah MixinDefinition dan jika _is_, lewati bingkai x pada tumpukan itu, di mana x sama dengan jumlah bingkai pada tumpukan MixinDefinition .

(Pada dasarnya; ini melompati bingkai 'penutupan' yang ditambahkan ke dalam tumpukan ketika MixinCall mengeksekusi MixinDefinition .)

Menghapus label "basi". Ini masih merupakan masalah yang bagus untuk dijelajahi.

Mungkin current-selector() tidak terlalu buruk. Meskipun, untuk lebih jelasnya, itu sebenarnya adalah current-selectors() . Tapi itu masih agak bertele-tele. Saya pikir saya akan lebih mendukung jika kita bisa memikirkan nama fungsi untuk "menangkap &" yang lebih ringkas.

nama fungsi untuk "menangkap &" itu lebih ringkas.

Beri nama saja &() . Secara konseptual tidak lebih dari pengambil untuk apa yang ada di & .
Misalnya

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

🤔
Ya, itu seharusnya baik-baik saja. Ada keberatan?

Saya akan mencoba meringkas untuk melihat apakah saya memahami fitur yang diusulkan:

Fungsi baru &() mengembalikan apa yang & akan output dalam konteks saat ini, memungkinkan untuk ini.

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

Dan itu semua akan menghasilkan ini.

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

Karena itu luar biasa, dan saya menyukainya.

Memikirkan hal ini lebih lanjut, saya pikir yang paling menarik bagi saya (setelah umpan pertama; hentikan saya jika saya terlalu gila) adalah kemungkinan memiliki gaya komponen "blok" (aturan) standar. Pada dasarnya, saya hampir berharap bahwa alih-alih menyimpan nilai string pemilih sederhana, fungsi akan dipetakan ke _" & , tetapi dalam ruang lingkup variabel didefinisikan dalam"_, yang memungkinkan gaya penulisan ini untuk sebuah komponen (saya akan menyebutnya Behavior A ):

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

Lalu saya bisa mengatakan "gunakan @this mana-mana alih-alih & ".

Satu-satunya kekhawatiran saya adalah flip case (yang akan saya sebut Behavior B ), tetapi saya tidak dapat memikirkan kasus yang menarik di mana saya menginginkan perilaku itu. Itu sebabnya saya tidak mengerti mengapa seseorang ingin melakukan ini.

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

Karena cara saat ini untuk mencapainya _jauh_ lebih ringkas (dan juga dapat dibaca, setelah & jelas dalam kosakata Anda).

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

Apakah ada kasus yang menarik (selain dari kesulitan menerapkan) untuk Perilaku B daripada Perilaku A?

Ini hanyalah salah satu pertanyaan yang menurut saya harus dijawab sebelum pekerjaan dimulai.


TL;DR: Suara saya adalah untuk &() menjadi dinamis, yang pada dasarnya berarti _" & , tetapi seolah-olah bersarang di sini alih-alih lebih dalam"_, daripada mengembalikan _"statis nilai & sekarang."_

@calvinjuarez Contoh Anda agak membingungkan karena Anda tidak menulis hasil yang diharapkan, sehingga tampaknya agak dalam bidang teoretis, tetapi pada dasarnya:

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

pada dasarnya berarti "&, tetapi seolah-olah bersarang di sini alih-alih lebih dalam", daripada mengembalikan "nilai & sekarang" statis.

Saya benar-benar tidak mengerti apa artinya ini.

Cara lain untuk memikirkan hal ini. Ini:

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

Apakah setara dengan menulis:

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

@matthew-dean

Ya. Tapi pikirkanlah melalui lensa mixin, di mana &() akan mengambil konteks pemilih pemanggil mixin.

Ini memungkinkan penulisan komponen berbasis mixin di mana penulis sendiri dapat dengan bebas memutuskan akar nama kelas secara alami. Misal diberikan

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

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

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

mixin yang digunakan di sana dapat membaca kelas melalui &() dan mengerjakannya ke dalam output mereka dengan tepat. Misalnya, pemilih yang ditangkap untuk aturan kedua dan ketiga dapat membuat sintaks BEM didekomposisi untuk mendapatkan kelas blok dasar, yang dapat digunakan untuk menghasilkan penggantian untuk pemilih elemen bersarang.

Itu adalah; itu dapat digunakan untuk menghasilkan pemilih seperti .my-button--wide > .my-button__text , tanpa perlu memasukkan nama pemilih apa pun sebagai parameter. Hanya dari konteks pemilih callee saja.


_Pabrik komponen_ berbasis campuran seperti ini menghindari banyak masalah all-or-nothing our-or-the-highway yang Anda dapatkan dengan menggunakan kerangka penataan gaya. Mereka memungkinkan Anda untuk mendaftarkan kerangka kerja, tetapi secara terperinci memilih komponen mana yang benar-benar ingin Anda masukkan dan dengan nama yang mana.

@rjgotten

mixin yang digunakan di sana dapat membaca kelas melalui &() dan mengolahnya menjadi output dengan tepat. Misalnya, pemilih yang ditangkap untuk aturan kedua dan ketiga dapat membuat sintaks BEM didekomposisi untuk mendapatkan kelas blok dasar, yang dapat digunakan untuk menghasilkan penggantian untuk pemilih elemen bersarang.

Ya, saya mengerti. Ini mungkin paling berguna dalam mixin. Saya pasti mendapatkan utilitas &() daripada menggunakan nama pemilih langsung. Maksud saya hanya mencoba mengklarifikasi nilai &() dalam contoh yang diberikan.

Untuk melangkah lebih jauh, saya pikir ini adalah solusi sintaksis yang bagus, dan saya pribadi akan memberikan 👍 untuk bergerak maju dengan implementasi &() , jika seseorang ingin menggunakannya.

@matthew-dean

Contoh Anda agak membingungkan karena Anda tidak menulis hasil yang diharapkan

Ups, maaf. Saya akan menyatakannya kembali dengan benar. Saya merasa &() akan menjadi fitur yang lebih kuat jika Less here dikompilasi ke CSS di bawah ini.

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

Jika <strong i="15">@this</strong>:&(); berperilaku seperti <strong i="17">@this</strong>:.component; dalam kasus ini, kami menurunkan fitur ini ke utilitas _only_ di dalam mixin, tetapi menurut saya fitur ini memiliki lebih banyak hal untuk ditawarkan.

pada dasarnya berarti "&, tetapi seolah-olah bersarang di sini alih-alih lebih dalam", daripada mengembalikan "nilai & sekarang" statis.

Saya benar-benar tidak mengerti apa artinya ini.

Artinya menurut saya .thing{ & {} } dan .thing{ <strong i="11">@amp</strong>:&(); @{amp} {} } harus menghasilkan output yang sama.

Artinya, secara lebih praktis, Anda tidak perlu menulis mixin untuk membuat BEM yang mudah, tetapi dapat mendefinisikannya sebaris. Kembali ke salah satu contoh lama saya:

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

↓↓↓

_komponen.css_

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

Manfaatnya: Anda tidak perlu bertanya kepada tim apakah maksudnya & atau @{this} . Anda hanya mengatakan "Gunakan saja @{this} mana-mana."

Itu benar-benar akan membuat definisi mixin pabrik komponen lebih konsisten secara internal juga.

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

_hipothetical-styles.less_

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

_hypotthetical-styles.css_

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

Artinya menurut saya .thing{ & {} } dan .thing{ @amp :&(); @{amp} {} } harus menghasilkan keluaran yang sama.

Ya, saya pikir kami mengatakan hal yang sama tetapi izinkan saya mengkonfirmasi dengan contoh ini. Beginilah cara saya melihat fitur ini vs. di tempat & .

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

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

Sedangkan:

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

Akan menghasilkan:

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

@calvinjuarez Saya kira saya bingung karena saya pikir tidak ada yang menyarankan sesuatu yang berbeda dari contoh Anda. &() pada dasarnya akan seperti this.selectors.toCSS() dievaluasi di lokasi itu ( tidak juga, tetapi hanya untuk ilustrasi .... sebenarnya itu mungkin cara tercepat untuk melakukannya). Dan kemudian memasukkan string itu di tempat lain untuk dievaluasi kembali sebagai penyeleksi.

@matthew-dean
Sebenarnya akan lebih _lebih_ luar biasa jika itu akan mengekspos daftar pemilih sebagai daftar pemilih yang sebenarnya, termasuk perilaku khusus untuk memperluas pemilih berdasarkan semua anggota daftar.

punya misalnya

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

  @{this} {
    c : d;  
  }
}

keluaran

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

seperti & .

Ya, itulah yang akan dilakukannya. Dalam 3.5, setiap variabel yang dievaluasi dalam pemilih menyebabkan seluruh daftar pemilih diurai ulang sebagai daftar pemilih baru. Jadi ya, itu akan bekerja seperti yang diharapkan. Sebenarnya cukup mudah karena beberapa PR terakhir yang saya lakukan.

Pada 7 Juli 2018, pukul 10:34, rjgotten [email protected] menulis:

@matthew-dean
Sebenarnya akan lebih luar biasa jika itu akan mengekspos daftar pemilih sebagai daftar pemilih yang sebenarnya, termasuk perilaku khusus untuk memperluas pemilih berdasarkan semua anggota daftar.

punya misalnya

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

@{ini} {
c : d;
}
}
keluaran

.A A,
.a .b,
.B. .sebuah,
.a .b {
c : d
}
seperti yang asli & akan.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub, atau matikan utasnya.

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

Tambahan .component adalah apa yang saya perdebatkan. Saya menyarankan itu harus bekerja seperti ini:

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

Sepertinya fitur ini menuju ke arah yang berbeda. Hanya ingin memperjelas posisi saya.

Saya menyarankan itu harus bekerja seperti ini:

Yaitu jika ada token substitusi di pemilih yang merupakan _daftar pemilih_ alih-alih _string_ biasa, maka token substitusi bertindak sama seperti jika & ditentukan dan _menonaktifkan_ rangkaian pemilih normal yang dihasilkan dari bersarang.

Jika &() menghasilkan tipe simpul yang membuatnya dapat diidentifikasi sebagai daftar pemilih yang sebenarnya, perilaku itu akan relatif mudah dicapai, saya pikir.

Faktanya, jika itu adalah untuk menghasilkan tipe simpul khusus, itu mungkin juga membantu pembuatan fungsi plugin untuk _memanipulasi_ daftar pemilih yang diambil, nanti.

Bagi saya, itu terdengar seperti membuat &() melakukan terlalu banyak pekerjaan sekaligus. Jika Anda ingin menyimpan penyeleksi ke variabel, itu satu hal, tetapi variabel tersebut menonaktifkan rantai pemilih karena _content_-nya tidak jelas dalam sintaks. Variabel itu bisa datang dari mana saja (misalnya lulus dari mixin) dan daftar pemilih dapat dihasilkan dengan penetapan variabel sederhana. Artinya, tidak jelas dari penggunaan variabel bahwa perilaku rantai yang berbeda akan terjadi berdasarkan konten variabel.

Saya pikir jika Anda ingin menonaktifkan rantai, Anda harus menentukan bahwa Anda ingin mengganti implisit & dengan nilai lain, seperti (maafkan pemformatan, saya menggunakan ponsel saya) -

.komponen {
@var : &();
&(@var)_child {} // atau sintaks "penggantian &" semacam itu
}

Jadi saya mengerti mengapa hasilnya diinginkan, tetapi IMO kita tidak bisa hanya "beralih ajaib" perilaku penggabungan variabel berdasarkan dari mana daftar pemilih berasal. Ini membutuhkan dua fitur yang berbeda.

ooh... Saya sebenarnya suka hal &(...) ...

Benarkah? Anda tidak berpikir akan ada kebingungan semantik &() (tangkap pemilih dari &) dan &(@arg) (ganti & dengan pemilih)?

Anda mungkin ingin mempertimbangkan untuk tidak mencampurnya, karena seseorang mungkin ingin mengganti & dengan pemilih kosong untuk membuangnya pada dasarnya. (Untuk menempatkan anak di akar.) Meskipun saya kira mungkin itu bisa menjadi &(“”) .child?

Entahlah, itu layak untuk dipikirkan/dipertimbangkan.

Juga, seperti yang disebutkan dalam utas "pemilih induk harus memiliki target", ada kasus penggunaan untuk mengganti bagian tertentu dari pemilih yang diwarisi (atau seluruhnya), jadi memikirkan itu, saya pikir itu harus dilacak sebagai dua masalah terpisah. Masalah ini seharusnya hanya tentang menangkap &

Hanya untuk menutup lingkaran ini, di sinilah saya menyebutkan mengubah & di tempat dengan konstruksi seperti fungsi. - https://github.com/less/less.js/issues/1075#issuecomment -397697714

Jadi, saya lebih suka jika diskusi tentang "bagaimana/apakah mengubah warisan & " tetap ada di utas pemilih induk, dan utas ini tentang apakah <strong i="9">@var</strong>: &() sesuai untuk menangkap in -tempatkan pemilih & ke variabel. Yang, dalam pikiran saya, masih tampak baik-baik saja, terlepas dari utas lainnya. Saya tidak yakin apakah ada kesempatan untuk melakukan keduanya atau tidak.

Saya mencoba melakukan ini

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

tapi itu tidak akan berhasil sampai ini diimplementasikan

Apakah halaman ini membantu?
0 / 5 - 0 peringkat