Mengapa JavaScript melahap HTML: contoh kode

Pengembangan web terus berkembang. Baru-baru ini, satu tren telah menjadi populer, yang pada dasarnya bertentangan dengan gagasan yang diterima secara umum tentang bagaimana mengembangkan aplikasi web. Beberapa memiliki harapan tinggi untuknya, sementara yang lain kecewa. Masing-masing memiliki alasan sendiri untuk ini, yang singkatnya sulit untuk dijelaskan.



Kode halaman web secara tradisional terdiri dari tiga bagian, yang masing-masing memenuhi tugasnya: HTML-code mendefinisikan struktur dan semantik, CSS-code menentukan penampilan, dan JavaScript-code menentukan perilakunya. Dalam tim yang melibatkan desainer, pengembang HTML / CSS dan pengembang JavaScript, pemisahan ini wajar: desainer mendefinisikan elemen visual dan antarmuka pengguna, pengembang HTML dan CSS menempatkan elemen visual ini pada halaman di browser, dan pengembang JavaScript menambahkan interaksi pengguna ke ikat semuanya menjadi satu dan “buat itu bekerja.” Setiap orang dapat mengerjakan tugas mereka tanpa mengganggu kode dari dua kategori pengembang lainnya. Tetapi semua ini berlaku untuk apa yang disebut "gaya lama."

Dalam beberapa tahun terakhir, pengembang JavaScript mulai menentukan struktur halaman dalam JavaScript, dan bukan dalam HTML (misalnya, menggunakan kerangka kerja React js ), yang membantu menyederhanakan pembuatan dan pemeliharaan kode interaksi pengguna. Tanpa kerangka js, mengembangkan situs web modern jauh lebih sulit. Tentu saja, ketika Anda memberi tahu seseorang bahwa kode HTML yang ditulis olehnya perlu dipecah-pecah dan dicampur dengan JavaScript, yang sangat ia kenal, ini (untuk alasan yang jelas) dapat dirasakan dengan permusuhan. Paling tidak, lawan bicara akan bertanya mengapa kita membutuhkan ini sama sekali, dan bagaimana kita akan mendapat manfaat dari ini.

Sebagai pengembang JavaScript dalam tim lintas fungsi, pertanyaan ini terkadang ditanyakan kepada saya, dan seringkali sulit bagi saya untuk menjawabnya. Semua materi yang saya temukan pada topik ini ditulis untuk audiens yang sudah terbiasa dengan JavaScript. Dan ini tidak terlalu baik bagi mereka yang berspesialisasi secara khusus dalam HTML dan CSS. Tetapi pola HTML-in-JS (atau sesuatu yang memberikan manfaat yang sama) kemungkinan akan diminati untuk beberapa waktu, jadi saya pikir ini adalah hal penting yang harus dipahami oleh semua orang yang terlibat dalam pengembangan web.

Pada artikel ini saya akan memberikan contoh kode untuk mereka yang tertarik, tetapi tujuan saya adalah untuk menjelaskan pendekatan ini sehingga dapat dipahami tanpa mereka.

Likbez: HTML, CSS dan JavaScript


Untuk memaksimalkan khalayak artikel ini, saya ingin secara singkat berbicara tentang peran apa yang dimainkan bahasa ini dalam membuat halaman web, dan pemisahan seperti apa yang ada pada awalnya. Jika Anda semua tahu ini, Anda dapat melewati bagian ini.

HTML: untuk struktur dan semantik


Kode HTML (HyperText Markup Language) mendefinisikan struktur dan semantik konten yang akan ditempatkan pada halaman. Misalnya, kode HTML artikel ini berisi teks yang sedang Anda baca sekarang, dan sesuai dengan struktur yang ditentukan, teks ini ditempatkan dalam paragraf terpisah, setelah tajuk dan sebelum menempelkan CodePen .

Misalnya, buat halaman web sederhana dengan daftar belanja:



Kami dapat menyimpan kode ini dalam file, membukanya di browser web, dan browser akan menampilkan hasilnya. Seperti yang Anda lihat, kode HTML dalam contoh ini adalah halaman yang berisi tajuk "Daftar Belanja" (Item belanja (2 item)), kotak teks input, tombol "Tambah Item" dan daftar dua item ("Telur" dan "Minyak"). Pengguna akan memasukkan alamat di browser web-nya, kemudian browser akan meminta kode HTML ini dari server, unduh dan tampilkan. Jika sudah ada elemen dalam daftar, server dapat mengirim HTML dengan elemen siap pakai, seperti dalam contoh ini.

Coba ketikkan sesuatu di bidang input dan klik tombol "Tambahkan item". Anda akan melihat bahwa tidak ada yang terjadi. Tombol tidak terkait dengan kode apa pun yang dapat mengubah HTML, dan HTML tidak dapat mengubah apa pun dengan sendirinya. Kami akan kembali ke sini sebentar lagi.

CSS: untuk mengubah tampilan


Kode CSS (Cascading Style Sheets) mendefinisikan tampilan halaman. Misalnya, CSS dari artikel ini mendefinisikan font, spasi, dan warna teks yang Anda baca.

Anda mungkin telah memperhatikan bahwa contoh daftar belanja kami terlihat sangat sederhana. HTML tidak memungkinkan hal-hal seperti penspasian, ukuran font, dan warna ditentukan. Itu sebabnya kami menggunakan CSS. Kita bisa menambahkan kode CSS untuk halaman ini untuk menghiasnya sedikit:



Seperti yang Anda lihat, kode CSS ini mengubah ukuran dan ketebalan karakter teks, serta warna latar belakang. Pengembang dapat, secara analogi, menulis aturan untuk gayanya sendiri, dan aturan itu akan diterapkan secara berurutan ke struktur HTML apa pun: jika kita menambahkan elemen bagian, tombol, atau ul ke halaman ini , perubahan font yang sama akan berlaku.
Tetapi tombol Tambah Item masih tidak melakukan apa-apa: di sini kita hanya perlu JavaScript.

JavaScript: untuk menerapkan perilaku


Kode JavaScript mendefinisikan perilaku elemen-elemen interaktif, atau dinamis, pada suatu halaman. Misalnya, CodePen ditulis menggunakan JavaScript.

Agar tombol Tambah Item dalam contoh kami berfungsi tanpa JavaScript, kami perlu menggunakan kode HTML khusus untuk memaksanya mengirim data kembali ke server ( <form action \ u003d '...'> jika Anda tiba-tiba tertarik). Selain itu, browser akan memuat ulang versi terbaru dari seluruh file HTML tanpa menyimpan status halaman saat ini. Jika daftar belanja ini adalah bagian dari halaman web besar, semua yang dilakukan pengguna akan hilang. Tidak masalah berapa banyak piksel yang Anda turunkan saat membaca teks - ketika Anda me-restart server akan mengembalikan Anda ke awal, tidak masalah berapa menit video yang Anda tonton - ketika Anda me-restart, itu akan mulai lagi.

Begitulah cara semua aplikasi web digunakan untuk bekerja: setiap kali pengguna berinteraksi dengan halaman web, ia sepertinya menutup browser webnya dan membukanya lagi. Ini tidak terlalu penting untuk studi kasus sederhana, tetapi untuk halaman rumit yang besar, yang mungkin memerlukan waktu untuk memuat, pendekatan ini tidak efektif untuk browser atau server.

Jika kami ingin mengubah sesuatu pada halaman tanpa memuat ulang halaman ini sepenuhnya, kami perlu menggunakan JavaScript:



Sekarang, ketika kami mengetik teks di kolom input dan mengklik tombol Tambah Item, elemen baru kami ditambahkan ke daftar dan jumlah elemen di atas diperbarui! Dalam aplikasi nyata, kami juga akan menambahkan beberapa kode untuk mengirim item baru ke server di latar belakang sehingga muncul saat berikutnya halaman dimuat.

Memisahkan JavaScript dari HTML dan CSS dibenarkan bahkan dalam contoh sederhana ini. Interaksi yang lebih kompleks bekerja seperti ini: HTML dimuat dan ditampilkan, dan JavaScript kemudian diluncurkan untuk menambahkan sesuatu ke dalamnya dan mengubahnya. Namun, seiring dengan meningkatnya kompleksitas aplikasi web, kita perlu memonitor dengan hati-hati apa, di mana, dan kapan kode JavaScript kita berubah.

Jika kami terus mengembangkan aplikasi ini dengan daftar belanja, kami mungkin menambahkan tombol untuk mengedit atau menghapus item dari daftar. Misalkan kita menulis kode JavaScript untuk tombol yang menghapus elemen, tetapi lupa menambahkan kode yang memperbarui informasi tentang jumlah total elemen di bagian atas halaman. Tiba-tiba, kami mendapatkan kesalahan: setelah pengguna menghapus item, jumlah total yang ditunjukkan pada halaman tidak akan cocok dengan daftar!

Segera setelah kami melihat kesalahan, kami memperbaikinya dengan menambahkan baris totalText.innerHTML yang sama dari kode kami untuk Tambah Item ke kode untuk Hapus Item. Sekarang kami memiliki kode yang sama, yang digandakan di beberapa tempat. Kemudian, katakanlah, kami ingin mengubah kode ini sehingga alih-alih “(2 item)” di bagian atas halaman itu menampilkan “Item: 2”. Kami harus memastikan bahwa kami tidak lupa memperbarui kode ini di ketiga tempat: dalam HTML, dalam kode JavaScript untuk tombol Tambahkan Item dan dalam kode JavaScript untuk tombol Hapus Item. Jika tidak, kami akan memiliki kesalahan lain, karena itu teks ini akan berubah secara dramatis setelah berinteraksi dengan pengguna.

Sudah dalam contoh sederhana ini, kita melihat betapa mudahnya bingung dalam kode. Tentu saja. Ada beberapa pendekatan dan praktik untuk merampingkan kode JavaScript untuk mempermudah penyelesaian masalah ini. Namun, ketika keadaan menjadi lebih rumit, kami harus terus merestrukturisasi dan terus-menerus menulis ulang proyek sehingga dapat dengan mudah dikembangkan dan dipelihara. Sementara HTML dan JavaScript disimpan secara terpisah, butuh banyak upaya untuk memastikan sinkronisasi antara keduanya. Ini adalah salah satu alasan kerangka kerja JavaScript baru seperti Bereaksi menjadi populer: mereka dirancang untuk memberikan hubungan yang lebih formal dan efisien antara HTML dan JavaScript. Untuk memahami bagaimana ini bekerja, pertama-tama kita perlu sedikit lebih jauh ke dalam ilmu komputer.

Pemrograman imperatif vs deklaratif


Hal utama yang harus dipahami adalah perbedaan dalam berpikir. Sebagian besar bahasa pemrograman memungkinkan Anda untuk mengikuti hanya satu paradigma, meskipun beberapa dari mereka mendukung dua paradigma sekaligus. Sangat penting untuk memahami kedua paradigma untuk menghargai keunggulan utama HTML-in-JS dari sudut pandang pengembang JavaScript.

  • . «» , . ( ) : , , . , , . - «». Vanilla JavaScript , jQuery. JavaScript .
    • « X, Y, Z».
    • : , .selected; , .selected.

  • . , . , , «» (), , - . , . (, React), , , . , , , , . , :
    • « XYZ. , , .
    • Contoh: elemen ini memiliki kelas. Terpilih jika pengguna memilihnya.


HTML adalah bahasa deklaratif


Lupakan JavaScript sejenak. Inilah fakta penting: HTML adalah bahasa deklaratif. Di file HTML, Anda dapat mendeklarasikan sesuatu seperti:

<section>
  <h1>Hello</h1>
  <p>My name is Mike.</p>
</section>

Saat peramban web membaca kode HTML ini, ia akan secara mandiri menentukan langkah-langkah yang diperlukan dan melakukannya:

  1. Buat elemen bagian .
  2. Buat elemen header level 1 ( h1 ).
  3. Setel teks elemen judul menjadi "Halo".
  4. Tempatkan elemen judul di elemen bagian.
  5. Buat elemen paragraf ( p ).
  6. Setel teks elemen paragraf ke "Nama saya adalah Mike".
  7. Tempatkan elemen paragraf di elemen bagian .
  8. Tempatkan elemen bagian dalam dokumen HTML.
  9. Tampilkan dokumen di layar.

Untuk pengembang web, bagaimana tepatnya browser melakukan hal-hal ini tidak masalah: semua yang penting adalah apa yang dilakukannya. Ini adalah contoh yang bagus untuk menggambarkan perbedaan antara dua paradigma pemrograman. Singkatnya, HTML adalah abstraksi deklaratif melilit mesin rendering browser web yang diimplementasikan secara imperatif. Dia peduli bagaimana, jadi kamu hanya perlu khawatir tentang apa. Anda dapat menikmati hidup sambil menulis HTML deklaratif karena orang-orang baik dari Mozilla, Google dan Apple menulis kode penting untuk Anda ketika mereka membuat browser web Anda.

JavaScript adalah bahasa yang sangat penting


Kami telah memeriksa contoh sederhana JavaScript imperatif dalam contoh daftar belanja di atas, dan saya menjelaskan bagaimana kompleksitas fungsi aplikasi memengaruhi upaya yang diperlukan untuk mengimplementasikannya dan kemungkinan kesalahan dalam implementasi ini.

Sekarang mari kita lihat tugas yang sedikit lebih kompleks dan lihat bagaimana hal itu dapat disederhanakan menggunakan pendekatan deklaratif. Bayangkan sebuah halaman web yang berisi yang berikut ini:

  • daftar bendera yang ditandai, setiap baris yang berubah warna saat dipilih;
  • teks di bawah ini, misalnya, "1 dari 4 dipilih", yang harus diperbarui ketika bendera diubah;
  • Pilih tombol Semua, yang harus dinonaktifkan jika semua kotak centang sudah dipilih;
  • Pilih tombol Tidak Ada, yang harus dinonaktifkan jika kotak centang tidak dipilih.

Berikut ini adalah implementasi dalam HTML biasa, CSS, dan JavaScript imperatif:



const captionText = document.getElementById('caption-text');
const checkAllButton = document.getElementById('check-all-button');
const uncheckAllButton = document.getElementById('uncheck-all-button');
const checkboxes = document.querySelectorAll('input[type="checkbox"]');

function updateSummary() {
  let numChecked = 0;
  checkboxes.forEach(function(checkbox) {
    if (checkbox.checked) {
      numChecked++;
    }
  });
  captionText.innerHTML = `${numChecked} of ${checkboxes.length} checked`;
  if (numChecked === 0) {
    checkAllButton.disabled = false;
    uncheckAllButton.disabled = true;
  } else {
    uncheckAllButton.disabled = false;
  }
  if (numChecked === checkboxes.length) {
    checkAllButton.disabled = true;
  }
}

checkAllButton.addEventListener('click', function() {
  checkboxes.forEach(function(checkbox) {
    checkbox.checked = true;
    checkbox.closest('tr').className = 'checked';
  });
  updateSummary();
});

uncheckAllButton.addEventListener('click', function() {
  checkboxes.forEach(function(checkbox) {
    checkbox.checked = false;
    checkbox.closest('tr').className = '';
  });
  updateSummary();
});

checkboxes.forEach(function(checkbox) {
  checkbox.addEventListener('change', function(event) {
    checkbox.closest('tr').className = checkbox.checked ? 'checked' : '';
    updateSummary();
  });
});

Sakit kepala apa adanya


Untuk mengimplementasikan fungsi ini menggunakan JavaScript imperatif, kita perlu memberi browser beberapa instruksi terperinci. Ini adalah deskripsi verbal dari kode dari contoh di atas.
Dalam HTML kami, kami mendeklarasikan struktur halaman asli:
  • Ada empat elemen baris (satu baris tabel, ini adalah daftar), yang masing-masingnya berisi bendera. Bendera ketiga dicentang.
  • Ada teks "1 dari 4 yang dipilih".
  • Ada tombol Select All yang dinyalakan.
  • Ada tombol Pilih Tidak Ada, yang dinonaktifkan.

Dalam JavaScript kami, kami menulis instruksi tentang apa yang perlu diubah ketika masing-masing peristiwa ini terjadi:
Ketika sebuah bendera berubah dari tidak ditandai menjadi ditandai:
  • Temukan baris yang berisi kotak centang dan tambahkan kelas CSS. Dipilih untuk itu.
  • Temukan semua bendera dalam daftar dan hitung berapa banyak yang ditandai dan berapa banyak yang tidak.
  • Temukan teks dan perbarui, yang menunjukkan jumlah pembelian yang dipilih dan jumlah total yang benar.
  • Temukan tombol Pilih Tidak Ada dan nyalakan jika dinonaktifkan.
  • Jika semua kotak centang sekarang dicentang, cari tombol Pilih Semua dan matikan.

Saat bendera berubah dari ditandai menjadi tidak ditandai:
  • Temukan baris yang berisi flag dan hapus kelas yang dipilih dari itu.
  • Temukan semua kotak centang dalam daftar dan hitung berapa banyak yang dicentang dan berapa banyak yang tidak.
  • Temukan item teks resume dan perbarui dengan nomor dan total yang diverifikasi.
  • Temukan tombol Select All dan nyalakan jika dinonaktifkan.
  • Jika semua kotak tidak dicentang, temukan tombol Pilih Tidak Ada dan matikan.

Ketika tombol Pilih Semua ditekan:
  • Temukan semua kotak centang dalam daftar dan tandai.
  • Temukan semua baris dalam daftar dan tambahkan kelas. Terpilih ke mereka.
  • Temukan teks dan perbarui.
  • Temukan tombol Select All dan matikan.
  • Temukan tombol Pilih Tidak Ada dan nyalakan.

Ketika tombol Pilih Tidak Ada ditekan:
  • Temukan semua kotak centang dalam daftar dan kosongkan semua kotak centang.
  • Temukan semua baris dalam daftar dan hapus kelas yang dipilih dari mereka.
  • Temukan elemen teks resume dan perbarui.
  • Temukan tombol Select All dan nyalakan.
  • Temukan tombol Pilih Tidak Ada dan matikan.

Wow ... Itu banyak, bukan? Sebaiknya kita tidak lupa menulis kode untuk semua situasi yang mungkin terjadi. Jika kita lupa atau mengacaukan salah satu dari petunjuk ini, kita akan mendapatkan kesalahan: totalnya tidak akan cocok dengan kotak centang, atau tombol akan menyala yang tidak melakukan apa-apa ketika Anda mengkliknya, atau baris yang dipilih akan mendapatkan warna yang salah atau sesuatu namun, yang belum kami pikirkan dan tidak akan tahu sampai pengguna mengeluh.

Kami benar-benar memiliki masalah besar di sini: tidak ada entitas yang akan berisi informasi lengkap tentang negaraaplikasi kami (dalam hal ini, ini adalah jawaban untuk pertanyaan "bendera apa yang ditandai?") dan akan bertanggung jawab untuk memperbarui informasi ini. Bendera, tentu saja, tahu jika dicentang, tetapi kode CSS untuk baris tabel, teks, dan setiap tombol juga harus mengetahui hal ini. Lima salinan informasi ini disimpan secara terpisah di seluruh HTML, dan ketika itu berubah di salah satu tempat ini, pengembang JavaScript harus menangkap ini dan menulis kode penting untuk disinkronkan dengan perubahan di tempat lain.

Dan ini masih merupakan contoh sederhana dari satu komponen halaman kecil. Bahkan jika kumpulan instruksi ini terlihat seperti sakit kepala, bayangkan betapa rumit dan rapuhnya aplikasi web yang lebih besar ketika Anda perlu mengimplementasikan semua ini dalam JavaScript yang imperatif. Untuk banyak aplikasi web modern yang kompleks, solusi ini tidak berskala dari kata "sepenuhnya."

Kami mencari sumber kebenaran


Alat seperti Bereaksi memungkinkan penggunaan deklaratif dari JavaScript. Sama seperti HTML adalah abstraksi deklaratif atas instruksi untuk ditampilkan di browser web, jadi React adalah abstraksi deklaratif atas JavaScript.

Ingat bagaimana HTML memungkinkan kami untuk fokus pada struktur halaman daripada detail implementasi, dan bagaimana browser menampilkan struktur ini? Demikian pula, ketika kita menggunakan Bereaksi, kita dapat fokus pada struktur, mendefinisikannya berdasarkan data yang disimpan di satu tempat. Proses ini disebut pengikatan satu arah, dan lokasi data status aplikasi disebut "sumber kebenaran tunggal." Ketika sumber kebenaran berubah, Bereaksi akan secara otomatis memperbarui struktur halaman untuk kami. Dia akan menangani langkah-langkah yang diperlukan di belakang panggung, seperti halnya browser web untuk HTML. Meskipun Bereaksi digunakan sebagai contoh di sini, pendekatan ini juga bekerja untuk kerangka kerja lain seperti Vue.

Mari kita kembali ke daftar kotak centang kita dari contoh di atas. Dalam hal ini, “kebenaran” yang ingin kita ketahui agak ringkas: bendera mana yang diperiksa? Rincian lainnya (misalnya, teks, warna garis, tombol mana yang dihidupkan) sudah mendapatkan informasi berdasarkan sumber kebenaran. Dan mengapa mereka harus memiliki salinan informasi ini sendiri? Mereka harus menggunakan satu-satunya sumber kebenaran hanya-baca, dan semua elemen halaman harus “hanya tahu” kotak centang mana yang dicentang dan berperilaku sesuai. Anda dapat mengatakan bahwa baris tabel, teks dan tombol harus dapat secara otomatis menanggapi kotak centang tergantung pada apakah dicentang atau tidak ("lihat apa yang terjadi di sana?")

Katakan apa yang Anda inginkan (apa yang benar-benar Anda inginkan)


Untuk mengimplementasikan halaman ini dengan React, kita dapat mengganti daftar dengan beberapa deskripsi fakta sederhana:

  • Ada daftar nilai benar / salah yang disebut checkboxValues ​​yang menunjukkan bidang mana yang ditandai.
    • Contoh: checkboxValues ​​\ u003d [false, false, true, false]
    • Daftar ini menunjukkan bahwa kami memiliki empat bendera, hanya yang ketiga yang ditetapkan.

  • Untuk setiap nilai di kotak centang Nilai di tabel, ada baris yang:
    • memiliki kelas CSS yang disebut. dipilih jika nilainya benar, dan
    • berisi flag yang dicentang jika nilainya benar.

  • Ada elemen teks yang berisi teks "{x} dari {y} yang dipilih", di mana {x} adalah jumlah nilai sebenarnya di checkboxValues, dan {y} adalah jumlah total nilai dalam checkboxValues.
  • Ada tombol Pilih Semua yang diaktifkan jika kotak centang Nilai memiliki nilai palsu.
  • Select None, , checkboxValues ​​ true.
  • , checkboxValues.
  • Select All , checkboxValues ​​ true.
  • Select None checkboxValues ​​ false.

Anda akan melihat bahwa tiga paragraf terakhir masih merupakan instruksi imperatif ("Ketika ini terjadi, lakukan itu"), tetapi ini adalah satu-satunya kode imperatif yang perlu kita tulis. Ini adalah tiga baris kode, dan semuanya memperbarui satu sumber kebenaran.

Sisanya adalah pernyataan deklaratif ("ada ..."), yang sekarang dibangun langsung ke dalam definisi struktur halaman. Untuk melakukan ini, kami menulis kode untuk elemen kami menggunakan ekstensi sintaksis JavaScript khusus - JavaScript XML (JSX). Ini menyerupai HTML: JSX memungkinkan Anda untuk menggunakan sintaks seperti HTML untuk menggambarkan struktur antarmuka, serta JavaScript biasa. Ini memungkinkan kita untuk mencampur logika JS dengan struktur HTML, sehingga strukturnya bisa berbeda kapan saja. Itu semua tergantung pada isi checkboxValues.

Kami menulis ulang contoh kami di Bereaksi:



function ChecklistTable({ columns, rows, initialValues, ...otherProps }) {
  const [checkboxValues, setCheckboxValues] = React.useState(initialValues);
  
  function checkAllBoxes() {
    setCheckboxValues(new Array(rows.length).fill(true));
  }
  
  function uncheckAllBoxes() {
    setCheckboxValues(new Array(rows.length).fill(false));
  }
  
  function setCheckboxValue(rowIndex, checked) {
    const newValues = checkboxValues.slice();
    newValues[rowIndex] = checked;
    setCheckboxValues(newValues);
  }
  
  const numItems = checkboxValues.length;
  const numChecked = checkboxValues.filter(Boolean).length;
  
  return (
    <table className="pf-c-table pf-m-grid-lg" role="grid" {...otherProps}>
      <caption>
        <span>{numChecked} of {numItems} items checked</span>
        <button
          onClick={checkAllBoxes}
          disabled={numChecked === numItems}
          className="pf-c-button pf-m-primary"
          type="button"
        >
          Check all
        </button>
        <button
          onClick={uncheckAllBoxes}
          disabled={numChecked === 0}
          className="pf-c-button pf-m-secondary"
          type="button"
        >
          Uncheck all
        </button>
      </caption>
      <thead>
        <tr>
          <td />
          {columns.map(function(column) {
            return <th scope="col" key={column}>{column}</th>;
          })}
        </tr>
      </thead>
      <tbody>
        {rows.map(function(row, rowIndex) {
          const [firstCell, ...otherCells] = row;
          const labelId = `item-${rowIndex}-${firstCell}`;
          const isChecked = checkboxValues[rowIndex];
          return (
            <tr key={firstCell} className={isChecked ? 'checked' : ''}>
              <td className="pf-c-table__check">
                <input
                  type="checkbox"
                  name={firstCell}
                  aria-labelledby={labelId}
                  checked={isChecked}
                  onChange={function(event) {
                    setCheckboxValue(rowIndex, event.target.checked);
                  }}
                />
              </td>
              <th data-label={columns[0]}>
                <div id={labelId}>{firstCell}</div>
              </th>
              {otherCells.map(function(cell, cellIndex) {
                return (
                  <td key={cell} data-label={columns[1 + cellIndex]}>
                    {cell}
                  </td>
                );
              })}
            </tr>
          );
        })}
      </tbody>
    </table>
  );
};

function ShoppingList() {
  return (
    <ChecklistTable
      aria-label="Shopping list"
      columns={['Item', 'Quantity']}
      rows={[
        ['Sugar', '1 cup'],
        ['Butter', '½ cup'],
        ['Eggs', '2'],
        ['Milk', '½ cup'],
      ]}
      initialValues={[false, false, true, false]}
    />
  );
}

ReactDOM.render(
  <ShoppingList />,
  document.getElementById('shopping-list')
);


BEJ terlihat aneh. Ketika saya pertama kali menemukan ini, bagi saya tampaknya mustahil untuk melakukannya. Reaksi awal saya adalah: “Apa? HTML tidak boleh di dalam kode JavaScript! " Dan saya bukan satu-satunya. Namun, ini bukan HTML, tetapi JavaScript yang berpakaian seperti HTML. Sebenarnya, ini adalah solusi yang kuat.

Ingat 20 instruksi penting di atas? Sekarang kita memiliki tiga dari mereka. Instruksi imperatif (internal) lainnya Bereaksi sendiri dijalankan untuk kita di belakang layar - setiap kali checkboxValues ​​berubah.

Dengan kode ini, situasi tidak dapat lagi terjadi ketika teks atau warna garis tidak cocok dengan kotak centang, atau ketika tombol menyala, meskipun harus dinonaktifkan. Ada seluruh kategori kesalahan yang sekarang tidak bisa terjadi di aplikasi web kami. Semua pekerjaan dilakukan berdasarkan satu sumber kebenaran, dan kami pengembang dapat menulis lebih sedikit kode dan tidur lebih baik di malam hari. Yah, pengembang JavaScript, setidaknya ...

JavaScript mengalahkan HTML: kelaparan


Ketika aplikasi web menjadi lebih kompleks, mempertahankan pemisahan tugas klasik antara HTML dan JavaScript menjadi lebih menyakitkan. HTML pada awalnya dirancang untuk halaman web statis. Untuk menambahkan fungsi interaktif yang lebih kompleks di sana, perlu untuk mengimplementasikan logika yang sesuai dalam JavaScript imperatif, yang dengan setiap baris kode menjadi semakin membingungkan dan rapuh.

Keuntungan dari pendekatan modern: prediktabilitas, penggunaan kembali, dan kombinasi


Kemampuan untuk menggunakan satu sumber kebenaran adalah keunggulan paling penting dari model ini, tetapi memiliki keunggulan lain. Menentukan elemen halaman kami dalam kode JavaScript berarti bahwa kami dapat menggunakan kembali komponen (blok individual halaman web), mencegah kami menyalin dan menempelkan kode HTML yang sama di beberapa tempat. Jika kita perlu mengubah komponen, cukup ubah kodenya hanya di satu tempat. Dalam hal ini, perubahan akan terjadi di semua salinan komponen (di dalam satu atau bahkan di banyak aplikasi web, jika kita menggunakan komponen yang dapat digunakan kembali di dalamnya).

Kita dapat mengambil komponen sederhana dan menyatukannya seperti kubus LEGO, membuat komponen yang lebih kompleks dan berguna tanpa membuat logikanya terlalu membingungkan. Dan jika kita menggunakan komponen yang dibuat oleh pengembang lain, kita dapat dengan mudah menggulung pembaruan atau perbaikan bug tanpa harus menulis ulang kode kita.

JavaScript yang sama, hanya di profil


Manfaat ini memiliki kerugian. Ada alasan bagus mengapa orang menghargai pemisahan HTML dan JavaScript. Seperti yang saya sebutkan sebelumnya, meninggalkan file HTML biasa mempersulit alur kerja untuk seseorang yang belum pernah bekerja dengan JavaScript sebelumnya. Mereka yang sebelumnya dapat secara mandiri membuat perubahan pada aplikasi web, sekarang harus memperoleh keterampilan rumit tambahan untuk mempertahankan otonomi mereka, atau bahkan menempatkannya dalam tim.

Ada juga kelemahan teknis. Misalnya, beberapa alat, seperti linter dan parser, hanya menerima HTML normal sebagai input, dan bekerja dengan plug-in JavaScript pihak ketiga mungkin lebih sulit. Selain itu, JavaScript bukan bahasa terbaik, tetapi standar yang diterima untuk peramban web. Alat dan fitur baru membuatnya lebih baik, tetapi masih ada beberapa jebakan di dalamnya yang perlu Anda ketahui sebelum bekerja dengannya.

Masalah potensial lainnya: ketika struktur semantik halaman dipecah menjadi komponen-komponen abstrak, pengembang mungkin berhenti memikirkan elemen HTML yang akan dihasilkan sebagai hasilnya. Tag HTML khusus seperti bagian dan samping, memiliki semantiknya sendiri, yang hilang ketika menggunakan tag tujuan umum seperti div dan span - bahkan jika mereka secara visual terlihat sama di halaman. Ini sangat penting untuk memastikan ketersediaan aplikasi web untuk berbagai kategori pengguna.

Sebagai contoh, ini akan mempengaruhi perilaku pembaca layar untuk pengguna tunanetra. Mungkin ini bukan tugas yang paling menarik bagi pengembang, tetapi pengembang JavaScript harus selalu ingat bahwa menjaga semantik HTML dalam hal ini adalah tugas yang paling penting .

Kebutuhan sadar vs tren tidak sadar


Baru-baru ini, penggunaan kerangka kerja di setiap proyek telah menjadi tren. Beberapa orang percaya bahwa pemisahan HTML dan JavaScript sudah usang, tetapi tidak. Untuk situs web statis sederhana yang tidak memerlukan interaksi pengguna yang rumit, ini tepat. Penggemar Bereaksi yang lebih bersemangat mungkin tidak setuju dengan saya di sini, tetapi jika semua JavaScript Anda lakukan adalah membuat halaman web non-interaktif, Anda tidak boleh menggunakannya. JavaScript tidak memuat secepat HTML biasa. Oleh karena itu, jika Anda tidak mengatur tugas untuk mendapatkan pengalaman pengembangan baru atau meningkatkan keandalan kode, JavaScript di sini akan lebih berbahaya daripada baik.

Selain itu, tidak perlu menulis seluruh situs web Anda di Bereaksi. Atau Vue! Atau apa lagi yang ada ... Banyak orang tidak tahu ini, karena semua tutorial pada dasarnya menunjukkan bagaimana menggunakan Bereaksi untuk mengembangkan situs dari awal. Jika Anda hanya memiliki satu widget kompleks kecil di situs web sederhana, Anda dapat menggunakan Bereaksi untuk satu komponen . Anda tidak harus selalu khawatir tentang paket web, Redux, Gatsby, atau apa pun yang seseorang sarankan sebagai "praktik terbaik" di sana.

Tetapi jika aplikasi ini cukup kompleks, menggunakan pendekatan deklaratif modern benar-benar layak. Apakah Bereaksi merupakan solusi terbaik? Tidak. Dia sudah memiliki pesaing yang kuat. Dan semakin banyak akan muncul ... Tapi pemrograman deklaratif tidak akan pergi ke mana pun, dan dalam beberapa kerangka kerja baru pendekatan ini mungkin akan dipikirkan kembali dan diimplementasikan lebih baik lagi.


All Articles