Kompilator sudut 200-garis

Hai Nama saya Roman, dan saya bukan penemu sepeda. Saya suka kerangka Angular dan ekosistem di sekitarnya, dan saya mengembangkan aplikasi web saya dengannya. Dari sudut pandang saya, keunggulan utama Angular dalam jangka panjang didasarkan pada pemisahan kode antara HTML dan TypeScript, yang dijelaskan secara rinci oleh salah satu pengembangnya mengapa-angular-renders-components-with.html Keuntungan ini memiliki kelemahan: kebutuhan untuk kompilasi pada prinsipnya dan kompleksitas komponen kompilasi dinamis dalam runtime. Dan saya ingin menggunakan sintaks template Angular yang sudah dikenal untuk memberi pengguna aplikasi mereka kemampuan untuk menyesuaikan template surat, menghasilkan laporan dan spreadsheet untuk dicetak, atau mengatur format ekspor untuk file xml! Untuk mengetahui bagaimana melakukan ini, selamat datang ke kucing!

Tantangan


Secara umum, penggunaan templat Angular oleh pengguna mungkin terlihat seperti ini: kami memiliki kumpulan data tertentu:

const data = { project: 'MySuperProject', userName: 'Roman', role: 'admin', projectLink: 'https://example.com/my-super-projectproject' } 

Penting untuk memberikan kesempatan untuk mengkonfigurasi teks surat, yang akan dikirim kepada pengguna setelah mengedit proyek. Menggunakan template Angular, mungkin terlihat seperti ini:

  <body>  !  {{project}}    <a href="{{projectLink}}">3D   </a> <div *ngIf="role == 'admin'">       <a href="{{projectLink}}?mode=edit"></a> </div> </body> 

Pustaka Ng-templat


Masalah ini dapat diselesaikan dengan menggunakan kompiler Angular pada klien (atau bahkan sisi server), tetapi sangat memakan waktu dan akan membutuhkan menyeret banyak megabyte kode ke klien. Mengapa kompiler Angular begitu besar? Ini disebabkan oleh fakta bahwa ia mendukung lautan beragam fungsi untuk menyusun komponen dan modul, dan juga mengandung pengurai HTML sendiri! Jadi saya memutuskan untuk menulis konverter template Angular minimal yang akan menggunakan parser HTML yang dibangun ke dalam browser. Itu mungkin dilakukan hanya dalam 200 dengan beberapa baris kode dalam beberapa jam. Saya memutuskan untuk membagikan hasilnya dengan publik di GitHub

Menggunakan perpustakaan ng-template cukup sederhana:

Instal ketergantungan dari npm

 npm install --save @quanterion/ng-template 

atau melalui benang

 yarn add @quanterion/ng-template 

Dan gunakan sebagai berikut:

 import { compileTemplate, htmlToElement } from '@quanterion/ng-template'; async test() { let data = { name: 'Roman' }; let element = htmlToElement(`<div>{{name}}</div>`); await compileTemplate(element, data); alert(element.outerHTML); } 

Sintaks yang didukung


  1. Ekspresi {{ekspresi}} dengan kemampuan untuk mengakses variabel dan fungsi panggilan
  2. Templat-templat
  3. Wadah
  4. Ketentuan * ngIf + * ngIf as
  5. Siklus * ngFor
  6. Gaya [style.xxx] = "value" dan [style.xxx.px] = "value"
  7. Kelas bersyarat [class.xxx] = "nilai"
  8. Observable {{name $}} dengan langganan otomatis ke suatu nilai (sebagai pipa async)

Lihat tes ng-template.spec.ts untuk lebih jelasnya.

Menggunakan Eval


Untuk mengevaluasi ekspresi dalam template, eval digunakan dengan preferensi dan pelacur. Faktanya adalah bahwa dalam template Sudut akses ke variabel digunakan tanpa awalan JavaScript biasa ini. Oleh karena itu, Anda perlu memanggil eval (), yang memiliki semua variabel dari objek data dalam lingkup. Saya tidak berhasil membuat kode seperti untuk eval (), karena lihat kode

 const data = { a: 1, b: () => 4 }; const expression = 'a+b()'; eval('a =1; b = ??;' + expression); 

tidak mengizinkan fungsi lewat

Solusinya ditemukan dengan membuat fungsi yang parameternya memiliki nama bidang objek dengan data:

 const data = { a: 1, b: () => 4 }; let entries = [] for (let property in data ) { entries.push([property, data[property]]) } const params = entries.map(e => e[0]); const fun = new Function('code', ...params, `return eval(code)`); const args = entries.map(e => e[1]); const expression = 'a+b()'; const result = fun.call(undefined, expression , ...args); 

NB: Saya berharap di masa depan, ketika API dari kompiler Ivy baru stabil, akan mungkin untuk menghasilkan seperangkat operator untuk Ivy dan membuat komponen lengkap dalam dinamika!

Tautan ke sumber

Source: https://habr.com/ru/post/id448022/


All Articles