Mustache.js: Mengakses cakupan induk

Dibuat pada 11 Des 2014  ·  18Komentar  ·  Sumber: janl/mustache.js

Mengakses cakupan induk

Mempertimbangkan :

node = {
  id: 1,
  children : [
      { id : 2 },
      { id : 3 }
  ]
}

Dan berikut templatenya:

{{ id }} {# will output node.id #}
{{#children}}
    {{children.id}}  {# will output node.children[i].id #}
    {{id}}  {# will also output node.children[i].id #}
{{/children}}

Karena itu, terkadang Anda harus mengakses properti induk (misalnya, dalam model simpul bersarang).
Itu dapat dengan mudah diimplementasikan seperti menggunakan "../" untuk mendapatkan cakupan induk

Mantan :

{{ id }} {# will output node.id #}
{{#children}}
    {{children.id}}  {# will output node.children[i].id #}
    {{id}}  {# will also output node.children[i].id #}
    {{ ../id }}  {# will output node.id #}
{{/children}}

Untuk mencapai itu:

  Context.prototype.lookup = function (name) {
    var cache = this.cache;

    var value;
    if (name in cache) {
      console.log(name + ' found');
      value = cache[name];
    } else {
      var context = this, names, index;

      while (context) {
        if (name.indexOf('.') > 0) {
          value = context.view;
          names = name.split('.');
          index = 0;

          while (value != null && index < names.length)
            value = value[names[index++]];
        } else if(name.match(/^\.\.\//)) {
          name = name.replace(/^\.\.\//, '');
        } else {
          value = context.view[name];
        }

        if (value != null)
          break;

        context = context.parent;
      }

      cache[name] = value;
    }

    if (isFunction(value))
      value = value.call(this.view);

    return value;
  };
Future Plugin

Komentar yang paling membantu

Benar. Saya benar-benar lupa tentang setang.

Mari kita kehilangan pengguna ke setang.
Itu keputusan desain yang dapat diterima.

Semua 18 komentar

Ini tidak ada dalam spesifikasi mustache , bukan? Tidak ada solusi untuk ini? Saya terkejut tidak ada yang menabrak batasan ini sebelumnya.

Saya setuju sering ada kebutuhan untuk mengakses hal-hal dalam lingkup induk. Pendekatan pragmatis saya selalu menghindari nama properti yang ambigu. Itu telah bekerja untuk waktu yang lama bagi saya, meskipun sering menghasilkan benda-benda aneh.

Di sisi lain, berbicara tentang pengalaman dengan setang; memiliki kemampuan ini mungkin menggoda orang untuk membuat resolusi lingkup induk kusut yang gila: {{../../../id}} jauh lebih sulit untuk dipahami daripada {{movieId}} .

Memang benar bahwa menggunakan "../" dapat menyebabkan tidak terbacanya. Tetapi dengan cara lain menggunakan caml untuk menyelesaikan induk tidak dapat dicapai karena Anda dapat memiliki caml dalam lingkup lokal. Selain itu, mendefinisikan kata kunci untuk mengakses orang tua tidak akan menghormati filosofi Kumis menurut saya.

berbicara terus terang saya tidak bisa sampai pada ide yang lebih sederhana dan lebih baik daripada menggunakan representasi direktori.

Ya, menghindari nama properti yang ambigu juga mengarah ke templat yang lebih mudah dibaca/verbose. Tapi saya mengerti mengapa beberapa orang menyukai fitur ini.

Bagaimana dengan menulis paket terpisah yang mengubah cara kerja bagian dalam mustache.js untuk menambahkan fitur yang diinginkan? Jenis seperti sebuah plugin.

Sejujurnya, saya tidak benar-benar melihat ini terjadi kecuali melalui plugin, atau pragma. Dan API plugin tampaknya tidak menjadi prioritas saat ini.

Aku sudah berpikir sedikit lebih tentang ini...

Saya percaya filosofi Kumis bukanlah untuk meneruskan data _as-is_ ke penyaji, tetapi untuk 'mempersiapkannya' ke dalam tampilan sebelumnya. Anda kemudian akan memiliki properti parentId di node Anda.

Juga lebih mudah untuk membaca dan memelihara template yang memiliki lebih banyak variabel verbose:

{{ id }}
{{#children}}
    {{children.id}}
    {{id}}
{{/children}}

Sebelum vs Setelah

{{ nodeId }}
{{#children}}
    {{ nodeId }}
    {{ parentId }}
{{/children}}

Relevan: http://stackoverflow.com/questions/4067093/mustache-read-variables-from-parent-section-in-child-section

(maaf memanggilmu @bobthecow , tapi aku selalu menghargai kebijaksanaan kumismu :senyum :)

Anda sudah bisa naik, jadi yang perlu dilakukan untuk memperbaiki masalah yang ditunjukkan dengan template pertama adalah membungkus data dengan objek temp {node: ... } , membungkus template dengan {{#node}}...{{/node}} dan kemudian {{node.id}} bagian dapat bekerja. Anda tidak perlu (dan tidak akan) mengubah data yang ada seperti itu, dan Anda dapat menambahkan kedua "JIT" itu saat Anda to_html() template...

terasa seperti pekerjaan yang tambal sulam. Ini juga hanya berfungsi dengan model 2 tingkat sederhana di mana Anda dapat menyelesaikannya dengan bungkus amplop untuk lapisan luar. Tetapi bagaimana jika modelnya lebih dalam? yang terasa juggling.

Seringkali saya perlu mengikat model yang saya dapatkan dari lapisan data yang lebih rendah, dan tugas saya adalah mempresentasikannya - dalam bentuk apa pun yang saya dapatkan dari infra. Proposisi di sini adalah bahwa saya harus mengonversi model secara rekursif sepenuhnya ke keadaan yang dapat dilihat - apa yang akan dipertimbangkan di sini redable property names .
Ini tidak memenuhi kenyataan dengan nyaman ...
Ya, benar, itu memasangkan template dengan model. Tapi bisakah Anda menunjukkan template yang tidak digabungkan dengan aturan model yang konkret? Semua template menurut definisi dibuat untuk membuat model yang ditentukan.
Lapisan lain memindahkan lapisan definisi satu langkah ke belakang, dan membutuhkan lapisan terjemahan - yang membosankan dan tidak selalu diperlukan

IMHO, saya pikir alat ini harus menyerahkan pilihan kepada pengguna, daripada memaksakan aturan yang berpendirian

Untuk pembaca, contoh dari apa yang disarankan @rndme :

const Mustache = require('mustache')

var view = {
  node: {
    id: 5,
    children: [ { id: 6 }, { id: 7 } ]
  }
}

const template = `
{{#node}}
  children:
  {{#children}}

    id: {{ id }}
    parentId: {{ node.id }}
  {{/children}}
{{/node}}
`

const output = Mustache.render(template, view)
console.log(output)

  children:

    id: 6
    parentId: 5

    id: 7
    parentId: 5

Menggunakan templat berikut tidak berfungsi pada latest , tetapi _itu harus berfungsi_, imo.

const template = `
  children:
  {{#node.children}}

    id: {{ id }}
    parentId: {{ node.id }}
  {{/node.children}}
`

Ya, benar, itu memasangkan template dengan model. Tapi bisakah Anda menunjukkan template yang tidak digabungkan dengan aturan model yang konkret? Semua template menurut definisi dibuat untuk membuat model yang ditentukan.
Lapisan lain memindahkan lapisan definisi satu langkah ke belakang dan membutuhkan lapisan terjemahan - yang membosankan dan tidak selalu diperlukan

Afaik, filosofi Kumis selalu bahwa Anda menghasilkan tampilan yang diteruskan ke template – Anda tidak melewatkan model secara langsung.

@osher Bisakah Anda menunjukkan kepada kami contoh yang tidak dapat Anda kerjakan dengan mudah dengan tip/trik yang disebutkan di atas?

Saya akan mencoba memberikan cuplikan nanti, tetapi pada dasarnya - dengan 3 level bersarang itu tidak akan berfungsi karena Anda tidak dapat membungkus level menengah - Anda harus mengubah sumber ke tampilan yang diproses.
Anda akan dapat mengakses tingkat atas yang dibungkus, tetapi Anda tidak memiliki solusi untuk tingkat menengah.

Ambil contoh dokumen angkuh, di mana Anda memiliki tingkat akar, tingkat jalur, tingkat kata kerja (dan masih banyak lagi tetapi mari kita berhenti di sini). Setiap level dapat menentukan direktif khusus - x-uses , yang merupakan direktif DI untuk lapisan implementasi.

Misalkan Anda ingin membuat dokumen HTML dari dokumen angkuh ini.
Anda memerlukan tabel datar yang menentukan untuk setiap pengendali operasi (tingkat kata kerja) DI yang diterimanya, dan dari lapisan apa yang mewarisinya.
Sementara semua info melekat dalam dokumen swagger - Anda sekarang memiliki masalah.

Berikutnya.
Coba gunakan kumis untuk menghasilkan kode yang mengimplementasikan API yang dijelaskan dalam dokumen yang mengembalikan respons tiruan berdasarkan respons default operasi.
Coba buat doclet yang menjelaskan apa yang diharapkan oleh pengembang pelaksana yang datang untuk menggantikan respons tiruan dengan logika nyata dalam konteks DI mereka dan secara spesifik tentang level apa yang mereka dapatkan.
Sama...

Bukan generasi HTML klasik - ya. tapi siapa bilang kumis hanya untuk HTML? ini adalah mesin templating, dan pembuatan kode biasanya diimplementasikan menggunakan mesin templat seperti itu ;)

Anda tidak lulus model secara langsung.

itu harus menjadi pilihan pengguna, bukan batasan / batasan

Saya akan memberi Anda satu contoh lagi, dan saya akan mencoba melakukannya tanpa mengkhianati saus rahasia.

Asumsikan struktur data pohon yang menggambarkan aset yang dimiliki oleh pemain dalam permainan strategi.
Pohon itu dapat mencapai sekitar 5 tingkat, misalnya:
Aliance -> Empire -> City -> Army -> Troops

Setiap level dapat memberikan bonus pengubah - misalnya - atau bonus serangan, bonus pertahanan, bonus kesehatan, dll.
Pengubah yang menangani statistik yang sama dijelaskan dengan nama yang sama di semua level, (terutama karena dihitung secara rekursif).
Anda perlu menggunakan mesin templat untuk menghadirkan simulator pertempuran yang akan membantu pemain memilih pasukan apa yang merupakan pasukan ideal untuk tantangan tertentu dengan menampilkan statistik pertempuran pasukan di pasukan - yang berada di level paling bawah, tetapi mengumpulkan pertempuran pengubah yang diberi nama dengan nama atribut yang sama di seluruh pohon.
Ini _sangat_ disederhanakan, tetapi berdasarkan kisah nyata di mana alat lain memecahkan masalah dengan sangat mudah, tanpa memerlukan lapisan terjemahan tengah.

Saya akan menambahkan kesulitan: Terkadang tentara dialokasikan di gugus tugas tingkat Aliansi.
Alliance -> Rally -> Troops
Alat harus cukup umum (rekursif polos) dan tidak bergantung pada level beton.

Saya menyelesaikannya dengan apa yang disebut kumis parsial, hanya saja saya tidak menggunakan kumis ...

@osher berkata:

itu harus menjadi pilihan pengguna, bukan batasan / batasan

Tidak ada keraguan kumis memiliki pendapat. Filosofi "logika template kurang" menempatkan banyak batasan pada template, fakta itu sering membutuhkan persiapan data/model sebelum memberikannya ke template untuk rendering. Jika ini tidak sesuai dengan kebutuhan Anda, ada alternatif yang mungkin lebih baik, seperti setang atau bahkan lodash.template hanya untuk beberapa nama

Benar. Saya benar-benar lupa tentang setang.

Mari kita kehilangan pengguna ke setang.
Itu keputusan desain yang dapat diterima.

Saya cukup yakin @osher sedang menyindir ketika dia mengatakan "Itu keputusan desain yang dapat diterima.", tetapi topik ini telah ditinggalkan sejak 2016. Apa yang terjadi? Sepertinya pertanyaan ini dihindari di repositori JavaScript ini dan juga di repositori utama:
https://github.com/mustache/mustache.github.com/issues/103

Saya sendiri berpikir bahwa dapat mereferensikan ruang lingkup induk tidak logis dan tidak boleh mengganggu cita-cita kumis.

Saya menyukai gagasan untuk selalu dapat mengakses ruang lingkup root dengan simbol, seperti "../" terkemuka:

Mustache.render('{{a1}}{{#a}}{{b.c}}{{../a1}}{{/a}}',{"a":{"b":{"c":"x1"}},"a1":"x2"})
"x2x1"

Saya ingin ini membuat "x2x1x2" tetapi menghilangkan yang terakhir karena bukan itu cara kerjanya.
Saya pikir saya akan merekomendasikan menggunakan sesuatu seperti JSONPath: https://goessner.net/articles/JsonPath/index.html#e2 namun tidak seperti XPath untuk XML, itu tidak merekomendasikan/mengimplementasikan operator induk, yang saya harapkan untuk.

Mungkin Kumis bisa mencoba untuk tetap kompatibel dengan setang dan menggunakan sintaks ../ untuk konteks induk?

AFAIK, setang hanya JS, sementara kumis menggunakan sintaks yang sama di banyak lingkungan, PHP misalnya. Jika Anda ingin mengubah sintaks kumis, Anda perlu meyakinkan semua implementasi non-js lainnya untuk melakukan hal yang sama; urutan yang tinggi. Selanjutnya, dalam memodifikasi kode JS, saya merasa bermasalah untuk naik "satu tingkat", meskipun saya menambahkan cara untuk kembali ke root di fork saya , yang cukup sederhana untuk diterapkan ...

Apa saja tentang ini?

Juga perlu ada dokumentasi dan rekomendasi gaya untuk situasi di mana notasi titik adalah opsional.

view = { wrap: { txt: "test" } };
{{#wrap}}
  {{wrap.txt}} {{! Should I use this?}}
  {{txt}} {{! Or this?}}
{{/wrap}}

Lebih detail di sini: https://stackoverflow.com/q/62166467/5637701

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

rlightner picture rlightner  ·  7Komentar

connor11528 picture connor11528  ·  3Komentar

Immortalin picture Immortalin  ·  12Komentar

mbrodala picture mbrodala  ·  16Komentar

zekth picture zekth  ·  18Komentar